Skip to content

Commit 64119f3

Browse files
Jabenclaude
andcommitted
Convert LinqPad examples to .NET 8 console applications
- Created 9 new console app examples in /examples directory - Converted all LinqPad scripts to standalone console applications - Updated all examples to use latest API (v2.8.1) - WithDimensions() → WithPageProperties() - PdfFormats → LibrePdfFormats - Removed deprecated SetUserAgent() and SetEmulatedMediaType() - Removed obsolete EnableNativePdfFormat() - Updated LibrePdfFormats.A1a → A2b (A1a deprecated in Gotenberg 7.6+) - Added centralized configuration via Directory.Build.props - Common PropertyGroup settings (target framework, nullable, etc.) - Shared package references (Microsoft.Extensions.*) - Shared project reference to Gotenberg.Sharp.Api.Client - Automatic resource copying to output directories - Added shared appsettings.json for all examples - Moved and renamed resources to lowercase /examples/resources/ for cross-platform compatibility - Created comprehensive examples/README.md with usage instructions - Updated main README.md to reference examples instead of linqpad folder - All examples build successfully with 0 errors and 0 warnings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent b566d5b commit 64119f3

49 files changed

Lines changed: 673 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public void ConfigureServices(IServiceCollection services)
8686

8787
```
8888
# Using GotenbergSharpClient
89-
*See the [linqPad folder](linqpad/)* for complete examples.
89+
*See the [examples folder](examples/)* for complete working examples as console applications.
9090

9191
## Required Using Statements
9292
```csharp
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
</Project>

examples/DIExample/Program.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using Gotenberg.Sharp.API.Client;
2+
using Gotenberg.Sharp.API.Client.Domain.Builders;
3+
using Gotenberg.Sharp.API.Client.Domain.Builders.Faceted;
4+
using Gotenberg.Sharp.API.Client.Domain.Requests;
5+
using Gotenberg.Sharp.API.Client.Domain.Settings;
6+
using Gotenberg.Sharp.API.Client.Extensions;
7+
using Microsoft.Extensions.Configuration;
8+
using Microsoft.Extensions.DependencyInjection;
9+
using Microsoft.Extensions.Logging;
10+
11+
// Builds a simple DI container with logging enabled.
12+
// Client retrieved through the service provider is configured with options defined in appsettings.json
13+
// Watch the polly-retry policy in action:
14+
// Turn off gotenberg, run this script and let it fail/retry two or three times.
15+
// Turn gotenberg back on & the request will successfully complete.
16+
// Example builds a 1 page PDF from the specified TargetUrl
17+
18+
const string TargetUrl = "https://www.cnn.com";
19+
var saveToPath = args.Length > 0 ? args[0] : Path.Combine(Directory.GetCurrentDirectory(), "output");
20+
Directory.CreateDirectory(saveToPath);
21+
22+
var services = BuildServiceCollection();
23+
var sp = services.BuildServiceProvider();
24+
25+
var sharpClient = sp.GetRequiredService<GotenbergSharpClient>();
26+
var request = await CreateUrlRequest();
27+
var response = await sharpClient.UrlToPdfAsync(request);
28+
29+
var resultPath = Path.Combine(saveToPath, $"GotenbergFromUrl-{DateTime.Now:yyyyMMddHHmmss}.pdf");
30+
31+
using (var destinationStream = File.Create(resultPath))
32+
{
33+
await response.CopyToAsync(destinationStream);
34+
}
35+
36+
Console.WriteLine($"PDF created: {resultPath}");
37+
38+
IServiceCollection BuildServiceCollection()
39+
{
40+
var config = new ConfigurationBuilder()
41+
.SetBasePath(AppContext.BaseDirectory)
42+
.AddJsonFile("appsettings.json")
43+
.Build();
44+
45+
return new ServiceCollection()
46+
.AddOptions<GotenbergSharpClientOptions>()
47+
.Bind(config.GetSection(nameof(GotenbergSharpClient))).Services
48+
.AddGotenbergSharpClient()
49+
.Services.AddLogging(s => s.AddSimpleConsole(ops =>
50+
{
51+
ops.IncludeScopes = true;
52+
ops.SingleLine = false;
53+
ops.TimestampFormat = "hh:mm:ss ";
54+
}));
55+
}
56+
57+
Task<UrlRequest> CreateUrlRequest()
58+
{
59+
var builder = new UrlRequestBuilder()
60+
.SetUrl(TargetUrl)
61+
.ConfigureRequest(b => b.SetPageRanges("1-2"))
62+
.WithPageProperties(b =>
63+
{
64+
b.SetPaperSize(PaperSizes.A4)
65+
.SetMargins(Margins.None);
66+
});
67+
68+
return builder.BuildAsync();
69+
}

examples/Directory.Build.props

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<Project>
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<ProjectReference Include="..\..\src\Gotenberg.Sharp.Api.Client\Gotenberg.Sharp.Api.Client.csproj" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
15+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
16+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
17+
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
18+
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
19+
<PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" />
20+
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
21+
</ItemGroup>
22+
23+
<ItemGroup>
24+
<None Include="..\appsettings.json" Link="appsettings.json">
25+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
26+
</None>
27+
<None Include="..\resources\**\*.*" Link="resources\%(RecursiveDir)%(Filename)%(Extension)">
28+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
29+
</None>
30+
</ItemGroup>
31+
</Project>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
</Project>

examples/HtmlConvert/Program.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using Gotenberg.Sharp.API.Client;
2+
using Gotenberg.Sharp.API.Client.Domain.Builders;
3+
using Gotenberg.Sharp.API.Client.Domain.Builders.Faceted;
4+
5+
var destinationDirectory = args.Length > 0 ? args[0] : Path.Combine(Directory.GetCurrentDirectory(), "output");
6+
Directory.CreateDirectory(destinationDirectory);
7+
8+
var resourcePath = Path.Combine(AppContext.BaseDirectory, "resources", "Html", "ConvertExample");
9+
var path = await CreateFromHtml(destinationDirectory, resourcePath);
10+
11+
Console.WriteLine($"PDF created: {path}");
12+
13+
static async Task<string> CreateFromHtml(string destinationDirectory, string resourcePath)
14+
{
15+
var sharpClient = new GotenbergSharpClient("http://localhost:3000");
16+
17+
var builder = new HtmlRequestBuilder()
18+
.AddAsyncDocument(async doc =>
19+
doc.SetBody(await GetHtmlFile(resourcePath, "body.html"))
20+
.SetFooter(await GetHtmlFile(resourcePath, "footer.html"))
21+
).WithPageProperties(dims => dims.UseChromeDefaults())
22+
.WithAsyncAssets(async assets =>
23+
assets.AddItem("ear-on-beach.jpg", await GetImageBytes(resourcePath))
24+
)
25+
.SetConversionBehaviors(b =>
26+
b.AddAdditionalHeaders("hello", "from-earth")
27+
)
28+
.ConfigureRequest(b => b.SetPageRanges("1"));
29+
30+
var request = await builder.BuildAsync();
31+
32+
var resultPath = Path.Combine(destinationDirectory, $"GotenbergFromHtml-{DateTime.Now:yyyyMMddHHmmss}.pdf");
33+
var response = await sharpClient.HtmlToPdfAsync(request);
34+
35+
using (var destinationStream = File.Create(resultPath))
36+
{
37+
await response.CopyToAsync(destinationStream);
38+
}
39+
40+
return resultPath;
41+
}
42+
43+
static Task<byte[]> GetImageBytes(string resourcePath)
44+
{
45+
return File.ReadAllBytesAsync(Path.Combine(resourcePath, "ear-on-beach.jpg"));
46+
}
47+
48+
static Task<byte[]> GetHtmlFile(string resourcePath, string fileName)
49+
{
50+
return File.ReadAllBytesAsync(Path.Combine(resourcePath, fileName));
51+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
</Project>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using Gotenberg.Sharp.API.Client;
2+
using Gotenberg.Sharp.API.Client.Domain.Builders;
3+
4+
var destinationDirectory = args.Length > 0 ? args[0] : Path.Combine(Directory.GetCurrentDirectory(), "output");
5+
Directory.CreateDirectory(destinationDirectory);
6+
7+
var resourcePath = Path.Combine(AppContext.BaseDirectory, "resources", "Markdown");
8+
var path = await CreateFromMarkdown(destinationDirectory, resourcePath);
9+
10+
Console.WriteLine($"PDF created from Markdown: {path}");
11+
12+
static async Task<string> CreateFromMarkdown(string destinationDirectory, string resourcePath)
13+
{
14+
var sharpClient = new GotenbergSharpClient("http://localhost:3000");
15+
16+
var builder = new HtmlRequestBuilder()
17+
.AddAsyncDocument(async b =>
18+
b.SetHeader(await GetFile(resourcePath, "header.html"))
19+
.SetBody(await GetFile(resourcePath, "index.html"))
20+
.SetContainsMarkdown()
21+
.SetFooter(await GetFile(resourcePath, "footer.html"))
22+
).WithPageProperties(b =>
23+
{
24+
b.UseChromeDefaults()
25+
.SetLandscape()
26+
.SetScale(.90);
27+
}).WithAsyncAssets(async b =>
28+
b.AddItems(await GetMarkdownAssets(resourcePath))
29+
)
30+
.ConfigureRequest(b => b.SetResultFileName("hello.pdf"))
31+
.SetConversionBehaviors(b => b.SetBrowserWaitDelay(2));
32+
33+
var request = await builder.BuildAsync();
34+
var response = await sharpClient.HtmlToPdfAsync(request);
35+
36+
var outPath = Path.Combine(destinationDirectory, $"GotenbergFromMarkDown-{DateTime.Now:yyyyMMddHHmmss}.pdf");
37+
38+
using (var destinationStream = File.Create(outPath))
39+
{
40+
await response.CopyToAsync(destinationStream);
41+
}
42+
43+
return outPath;
44+
}
45+
46+
static async Task<string> GetFile(string resourcePath, string fileName)
47+
=> await File.ReadAllTextAsync(Path.Combine(resourcePath, fileName));
48+
49+
static async Task<IEnumerable<KeyValuePair<string, string>>> GetMarkdownAssets(string resourcePath)
50+
{
51+
var bodyAssetNames = new[] { "img.gif", "font.woff", "style.css" };
52+
var markdownFiles = new[] { "paragraph1.md", "paragraph2.md", "paragraph3.md" };
53+
54+
var bodyAssetTasks = bodyAssetNames.Select(ba => GetFile(resourcePath, ba));
55+
var mdTasks = markdownFiles.Select(md => GetFile(resourcePath, md));
56+
57+
var bodyAssets = await Task.WhenAll(bodyAssetTasks);
58+
var mdParagraphs = await Task.WhenAll(mdTasks);
59+
60+
return bodyAssetNames.Select((name, index) => KeyValuePair.Create(name, bodyAssets[index]))
61+
.Concat(markdownFiles.Select((name, index) => KeyValuePair.Create(name, mdParagraphs[index])));
62+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
</Project>

examples/OfficeMerge/Program.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using Gotenberg.Sharp.API.Client;
2+
using Gotenberg.Sharp.API.Client.Domain.Builders;
3+
using Gotenberg.Sharp.API.Client.Domain.Builders.Faceted;
4+
5+
var sourceDirectory = args.Length > 0 ? args[0] : Path.Combine(AppContext.BaseDirectory, "resources", "OfficeDocs");
6+
var destinationDirectory = args.Length > 1 ? args[1] : Path.Combine(Directory.GetCurrentDirectory(), "output");
7+
Directory.CreateDirectory(destinationDirectory);
8+
9+
var path = await DoOfficeMerge(sourceDirectory, destinationDirectory);
10+
Console.WriteLine($"Merged Office documents PDF created: {path}");
11+
12+
static async Task<string> DoOfficeMerge(string sourceDirectory, string destinationDirectory)
13+
{
14+
var client = new GotenbergSharpClient("http://localhost:3000");
15+
16+
var builder = new MergeOfficeBuilder()
17+
.ConfigureRequest(c => c.SetTrace("ConsoleExample"))
18+
.WithAsyncAssets(async b => b.AddItems(await GetDocsAsync(sourceDirectory)))
19+
.SetPdfFormat(LibrePdfFormats.A2b)
20+
.SetPageRanges("1-3"); // Only one of the files has more than 1 page.
21+
22+
var response = await client.MergeOfficeDocsAsync(builder).ConfigureAwait(false);
23+
24+
var mergeResultPath = Path.Combine(destinationDirectory, $"GotenbergOfficeMerge-{DateTime.Now:yyyyMMddHHmmss}.pdf");
25+
26+
using (var destinationStream = File.Create(mergeResultPath))
27+
{
28+
await response.CopyToAsync(destinationStream).ConfigureAwait(false);
29+
}
30+
31+
return mergeResultPath;
32+
}
33+
34+
static async Task<IEnumerable<KeyValuePair<string, byte[]>>> GetDocsAsync(string sourceDirectory)
35+
{
36+
var paths = Directory.GetFiles(sourceDirectory, "*.*", SearchOption.TopDirectoryOnly);
37+
var names = paths.Select(p => new FileInfo(p).Name);
38+
var tasks = paths.Select(f => File.ReadAllBytesAsync(f));
39+
40+
var docs = await Task.WhenAll(tasks);
41+
42+
return names.Select((name, index) => KeyValuePair.Create(name, docs[index]))
43+
.Take(10);
44+
}

0 commit comments

Comments
 (0)