-
Notifications
You must be signed in to change notification settings - Fork 24
Add missing Chromium form fields with DDD value objects #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
18ed243
27956cf
480e387
cc045fd
d987f1b
7fc7265
9b26a91
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| using Gotenberg.Sharp.API.Client; | ||
| using Gotenberg.Sharp.API.Client.Domain.Builders; | ||
| using Gotenberg.Sharp.API.Client.Domain.Settings; | ||
| using Gotenberg.Sharp.API.Client.Infrastructure.Pipeline; | ||
|
|
||
| using Microsoft.Extensions.Configuration; | ||
|
|
||
| var config = new ConfigurationBuilder() | ||
| .SetBasePath(AppContext.BaseDirectory) | ||
| .AddJsonFile("appsettings.json") | ||
| .Build(); | ||
|
|
||
| var options = new GotenbergSharpClientOptions(); | ||
| config.GetSection(nameof(GotenbergSharpClient)).Bind(options); | ||
|
|
||
| var destinationDirectory = args.Length > 0 ? args[0] : Path.Combine(Directory.GetCurrentDirectory(), "output"); | ||
| Directory.CreateDirectory(destinationDirectory); | ||
|
|
||
| var path = await CreateWithChromiumFeatures(destinationDirectory, options); | ||
| Console.WriteLine($"PDF created: {path}"); | ||
|
|
||
| static async Task<string> CreateWithChromiumFeatures(string destinationDirectory, GotenbergSharpClientOptions options) | ||
| { | ||
| var handler = new HttpClientHandler(); | ||
| HttpMessageHandler effectiveHandler = handler; | ||
| if (!string.IsNullOrWhiteSpace(options.BasicAuthUsername) && !string.IsNullOrWhiteSpace(options.BasicAuthPassword)) | ||
| effectiveHandler = new BasicAuthHandler(options.BasicAuthUsername, options.BasicAuthPassword) { InnerHandler = handler }; | ||
|
|
||
| using var httpClient = new HttpClient(effectiveHandler, disposeHandler: true) | ||
| { | ||
| BaseAddress = options.ServiceUrl, | ||
| Timeout = options.TimeOut | ||
| }; | ||
|
|
||
| var sharpClient = new GotenbergSharpClient(httpClient); | ||
|
|
||
| // Demonstrates waitForSelector, emulated media features, and error handling options | ||
| var builder = new HtmlRequestBuilder() | ||
| .AddDocument(doc => doc.SetBody(@" | ||
| <html> | ||
| <head> | ||
| <style> | ||
| @media (prefers-color-scheme: dark) { | ||
| body { background: #1a1a2e; color: #eee; } | ||
| } | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <div id='content'> | ||
| <h1>Chromium Feature Demo</h1> | ||
| <p>This PDF was generated with dark mode emulation, waitForSelector, | ||
| and strict error handling.</p> | ||
| </div> | ||
| </body> | ||
| </html>")) | ||
| .SetConversionBehaviors(b => b | ||
| // Wait for the #content element before converting | ||
| .SetWaitForSelector("#content") | ||
| // Emulate dark mode | ||
| .AddEmulatedMediaFeature("prefers-color-scheme", "dark") | ||
| // Fail if the main page returns 4xx or 5xx | ||
| .SetFailOnHttpStatusCodes(499, 599) | ||
| // Fail if any resource fails to load | ||
| .FailOnResourceLoadingFailed() | ||
| // Fail on any console exceptions | ||
| .FailOnConsoleExceptions() | ||
| // Ignore CDN domains for status code checks | ||
| .AddIgnoreResourceHttpStatusDomains("cdn.example.com") | ||
| ) | ||
| .WithPageProperties(pp => pp.UseChromeDefaults()); | ||
|
|
||
| var request = builder.Build(); | ||
| var response = await sharpClient.HtmlToPdfAsync(request); | ||
|
|
||
| var resultPath = Path.Combine(destinationDirectory, $"ChromiumFeatures-{DateTime.Now:yyyyMMddHHmmss}.pdf"); | ||
|
|
||
| await using var destinationStream = File.Create(resultPath); | ||
| await response.CopyToAsync(destinationStream, CancellationToken.None); | ||
|
|
||
| return resultPath; | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -77,10 +77,15 @@ | |||||||
| return value switch | ||||||||
| { | ||||||||
| PdfFormat format => format.ToFormDataValue(), | ||||||||
| LibrePdfFormats format => format.ToFormDataValue(), | ||||||||
|
Check warning on line 80 in src/Gotenberg.Sharp.Api.Client/Domain/Requests/Facets/FacetBase.cs
|
||||||||
| ConversionPdfFormats format => format.ToFormDataValue(), | ||||||||
|
Check warning on line 81 in src/Gotenberg.Sharp.Api.Client/Domain/Requests/Facets/FacetBase.cs
|
||||||||
| PdfPassword password => password.Value, | ||||||||
| List<Cookie> cookies => JsonConvert.SerializeObject(cookies), | ||||||||
| List<EmulatedMediaFeature> features => JsonConvert.SerializeObject( | ||||||||
| features.ToDictionary(f => f.Name, f => f.Value)), | ||||||||
|
Comment on lines
+84
to
+85
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: For Gotenberg v8 Chromium routes, the exact expected form value shape for emulatedMediaFeatures is a JSON array of {name, value} objects. It is not a JSON object map. Citations:
🏁 Script executed: # Find and examine the EmulatedMediaFeature class
find . -name "EmulatedMediaFeature.cs" -type f | head -5Repository: ChangemakerStudios/GotenbergSharpApiClient Length of output: 162 🏁 Script executed: cat -n ./src/Gotenberg.Sharp.Api.Client/Domain/ValueObjects/EmulatedMediaFeature.csRepository: ChangemakerStudios/GotenbergSharpApiClient Length of output: 3573 🏁 Script executed: # Examine the FacetBase.cs file around lines 83-84
sed -n '75,95p' ./src/Gotenberg.Sharp.Api.Client/Domain/Requests/Facets/FacetBase.csRepository: ChangemakerStudios/GotenbergSharpApiClient Length of output: 1184 Serialize Lines 83-84 currently convert features to a dictionary via Serialize the list directly to preserve the array structure; the class's 💡 Proposed fix- List<EmulatedMediaFeature> features => JsonConvert.SerializeObject(
- features.ToDictionary(f => f.Name, f => f.Value)),
+ List<EmulatedMediaFeature> features => JsonConvert.SerializeObject(features),📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||
| List<GotenbergStatusCode> codes => JsonConvert.SerializeObject(codes.Select(c => c.Value)), | ||||||||
| List<DomainName> domains => JsonConvert.SerializeObject(domains.Select(d => d.Value)), | ||||||||
| CssSelector selector => selector.Value, | ||||||||
| OverlaySource overlaySource => overlaySource.ToFormValue(), | ||||||||
| SplitMode splitMode => splitMode.ToFormValue(), | ||||||||
| float f => f.ToString(cultureInfo), | ||||||||
|
|
||||||||
Uh oh!
There was an error while loading. Please reload this page.