PdfScriptCompiler 2.2.0

dotnet add package PdfScriptCompiler --version 2.2.0
                    
NuGet\Install-Package PdfScriptCompiler -Version 2.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PdfScriptCompiler" Version="2.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PdfScriptCompiler" Version="2.2.0" />
                    
Directory.Packages.props
<PackageReference Include="PdfScriptCompiler" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PdfScriptCompiler --version 2.2.0
                    
#r "nuget: PdfScriptCompiler, 2.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PdfScriptCompiler@2.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PdfScriptCompiler&version=2.2.0
                    
Install as a Cake Addin
#tool nuget:?package=PdfScriptCompiler&version=2.2.0
                    
Install as a Cake Tool

PdfScriptCompiler

NuGet NuGet Downloads License: MIT

Zero-dependency .NET 8 PDF compiler. Write plain markup or use the fluent C# API to generate real PDF binaries — no Word, no LaTeX, no third-party packages.

byte[] pdf = PdfScriptCompiler.Compile("""
    @page a4
    @title "Hello World"

    # Hello from PdfScriptCompiler

    Generate PDFs with **zero dependencies** in pure C#.
    """);

Table of Contents


Installation

dotnet add package PdfScriptCompiler

Or in your .csproj:

<PackageReference Include="PdfScriptCompiler" Version="2.2.0" />

Requirements: .NET 8 or later. No other dependencies.


Quick Start

using PdfScript;
using PdfScript.Core;

// 1. From markup string
byte[] pdf = PdfScriptCompiler.Compile("""
    @page a4
    @title "My Report"
    # Sales Report
    Revenue grew by **42%** this quarter.
    """);
File.WriteAllBytes("report.pdf", pdf);

// 2. From a .pdfs file
PdfScriptCompiler.CompileFile("report.pdfs", "report.pdf");

// 3. To a stream (ASP.NET Core response, memory, etc.)
PdfScriptCompiler.CompileToStream(source, Response.Body);

// 4. Fluent builder API
byte[] pdf2 = new PdfDocumentBuilder()
    .SetTitle("Invoice #1001")
    .AddHeading("Invoice #1001", 1)
    .AddTable(t => t
        .AddColumn(ColSpec.Star())
        .AddColumn(ColSpec.Fixed(80))
        .SetHeader("Item", "Amount")
        .AddRow("Consulting", "$1,200")
        .AddRow("Hosting",    "$80")
        .SetFooter(["Total", "$1,280"])
    )
    .Build();

Method 1 — PDFScript Markup Language

PDFScript is a lightweight plain-text format (.pdfs files) that compiles directly to PDF. It is designed to be readable as-is and writable by hand or by template engines.

Document Directives

Directives start with @ and must appear before any content.

Directive Syntax Description
@page @page a4 Page size: a4 letter a5 legal a3
@orientation @orientation landscape landscape or portrait (default)
@margin @margin 60 50 60 50 Top Right Bottom Left in pt. Also accepts 1 value (all sides) or 2 values (vertical horizontal)
@title @title "My Document" PDF metadata: document title
@author @author "Jane Doe" PDF metadata: author
@subject @subject "Q1 Report" PDF metadata: subject
@keywords @keywords "pdf report" PDF metadata: keywords
@encrypt @encrypt userpwd="open" ownerpwd="admin" permissions=all Password-protect the PDF
@watermark @watermark text="DRAFT" opacity=0.12 angle=45 Diagonal watermark on every page

Example — full document header:

@page a4
@orientation portrait
@margin 60 50 60 50
@title "Quarterly Report"
@author "Finance Team"
@subject "Q1 2026 Results"
@keywords "finance quarterly pdf"
@encrypt userpwd="open123" ownerpwd="admin456" permissions=all
@watermark text="CONFIDENTIAL" opacity=0.10 angle=45

Headings

# H1 — largest heading
## H2 — section heading
### H3 — sub-section heading
#### H4 — smallest heading

Paragraphs and Inline Styles

Any line that is not a directive or block element is a paragraph.

Syntax Result
**text** Bold
*text* Italic
***text*** Bold-Italic
`text` Monospace
[color=#ff0000]text[/color] Colored text
->text<- Centered paragraph
->text Right-aligned paragraph

Example:

This paragraph has **bold**, *italic*, ***bold-italic***, and `mono` text.

Here is [color=#cc0000]red[/color] and [color=#0055cc]blue[/color] inline.

->This paragraph is centered.<-

->This paragraph is right-aligned.

Comments — lines starting with // are ignored:

// This line will not appear in the PDF

Tables

.table [options]
| Header A | Header B | Header C |
| row data | row data | row data |
.end

Table options:

Option Default Description
cols="spec" equal star Column width specification (see below)
rowh=22 18 Minimum row height in pt
fontsize=9 9 Font size for all cell text
padding=5 5 Cell padding in pt
headerbg=#hex #1a2a5a Header row background colour
headerfg=#hex #ffffff Header row text colour
evenbg=#hex #f5f5f5 Even data row background colour
bordercol=#hex #b8b8b8 Border and divider colour

Column width specification (cols):

Specify widths as a space-separated list inside quotes:

Token Meaning Example
120 Fixed width in pt cols="60 120 80"
* Fill remaining space, weight 1 cols="auto * *"
*2 Fill remaining space, weight 2 cols="60 * *2"
auto Auto-fit to header text width cols="auto auto *"
// 3-column: auto ID, flexible description, fixed 80pt price
.table cols="auto * 80" fontsize=9 headerbg=#1a3a6b headerfg=#ffffff evenbg=#eef3ff
| Product        | Description                  | :Price:  |
| PDF Builder    | Full-featured PDF engine     | :$499:   |
| Support Bundle | 12-month priority support    | :$199:   |
.end

Cell alignment — wrap the cell value with colons:

Syntax Alignment
\| value \| Left (default)
\| :value: \| Center
\| value: \| Right
| Left cell | :Centered cell: | Right cell: |

Multi-page tables — the header row repeats automatically when the table spans multiple pages.


Boxes

A box is a highlighted content region with a background fill and optional border.

.box [bg=#eef3ff] [border=#99aadd] [pad=14]
Any block content — headings, paragraphs, tables, rules.
.end
Option Default Description
bg=#hex #edf0ff Background fill colour
border=#hex none Border colour (omit for no border)
pad=14 14 Internal padding in pt

Example:

.box bg=#fff8e0 border=#f0c060
## ⚠ Important Notice
Please read the terms carefully before signing.
.end

.box bg=#ffeef0 border=#ffaaaa
**Error:** The submitted value is invalid.
.end

Watermarks

A diagonal text overlay rendered behind all content on every page.

@watermark text="DRAFT" opacity=0.12 angle=45 fontsize=80
Option Default Description
text="..." DRAFT Watermark label
opacity=0.12 0.12 Intensity: 0 = invisible, 1 = solid black
angle=45 45 Rotation in degrees counter-clockwise
fontsize=80 80 Font size in pt

Common values:

@watermark text="DRAFT"         opacity=0.12  angle=45   // light diagonal
@watermark text="CONFIDENTIAL"  opacity=0.10  angle=30   // lighter, shallower
@watermark text="SAMPLE"        opacity=0.18  angle=45   // slightly darker
@watermark text="APPROVED"      opacity=0.12  angle=0    // horizontal

Page Breaks, Spacers, and Rules

<<<               Force a page break

.spacer 20        Vertical gap of 20 pt

---               Horizontal rule (default 0.5pt, light gray)

Raw PDF Operators

Inject content stream operators directly for custom graphics, shapes, or effects.

.raw
BT /F2 14 Tf 50 700 Td (Custom text via raw ops) Tj ET
.end
.raw
q
0.85 0.9 1.0 rg
50 600 495 80 re f
Q
.end

Warning: No bounds checking is performed on raw operators. Invalid operators will corrupt the page stream.


Method 2 — Fluent C# API

The PdfDocumentBuilder provides a fully programmatic way to construct PDFs without any markup.

PdfDocumentBuilder Reference

Document configuration:

var builder = new PdfDocumentBuilder()
    .SetTitle("My Document")        // PDF metadata
    .SetAuthor("Jane Doe")
    .SetSubject("Annual Report")
    .SetKeywords("pdf annual report")
    .SetPageSize(PageSize.A4)       // PageSize.A4 | Letter | A5 | Legal | A3
    .SetLandscape(true)             // true = landscape orientation
    .SetMargin(Margin.Normal)       // Margin.Normal | Narrow | Wide | All(v) | Symmetric(v,h)
    .SetEncryption(EncryptionSettings.PasswordProtect("open", "admin"))
    .SetWatermark("DRAFT", intensity: 0.12f, angleDeg: 45f, fontSize: 80f);

Content methods:

Method Description
.AddHeading(text, level) Heading level 1–4. Default level 1
.AddParagraph(markup, align) Paragraph supporting inline styles. Align: TextAlign.Left\|Center\|Right
.AddTable(Action<TableBuilder>) Table — configured via TableBuilder callback
.AddBox(Action<PdfDocumentBuilder>, background, border, padding) Highlighted content box
.AddRule(thickness, color) Horizontal rule. Default 0.5pt, light gray
.AddSpacer(pts) Vertical gap in pt. Default 12pt
.AddPageBreak() Force a new page
.AddRaw(operators) Inject raw PDF content stream operators

Output methods:

byte[] bytes = builder.Build();                  // returns byte[]
builder.BuildToFile("output.pdf");               // writes directly to disk

TableBuilder Reference

Configure via a callback passed to .AddTable():

builder.AddTable(t => t
    // Column widths (call once per column, in order)
    .AddColumn(ColSpec.Fixed(120))  // fixed 120pt
    .AddColumn(ColSpec.Star())      // fill remaining space
    .AddColumn(ColSpec.Star(2))     // fill with weight 2 (twice as wide as Star())
    .AddColumn(ColSpec.Auto)        // auto-size to header text

    // Row sizing
    .SetMinRowHeight(20)
    .SetFontSize(9)
    .SetPadding(5)

    // Styling
    .SetHeaderBackground(PdfColor.DarkBlue)
    .SetHeaderForeground(PdfColor.White)
    .SetEvenRowBackground(new PdfColor(0.95f, 0.97f, 1f))
    .SetBorderColor(new PdfColor(0.75f, 0.75f, 0.75f))
    .SetBorderWidth(0.4f)
    .SetRepeatHeader(true)          // repeat header row on page breaks

    // Data
    .SetHeader("No", "Product", "Description", "Price")
    .AddRow("1", "Alpha", "First product",  "$299")
    .AddRow("2", "Beta",  "Second product", "$149")

    // Optional footer (bold, appears after all data rows)
    .SetFooter(["", "", "Total", "$448"],
               [TextAlign.Left, TextAlign.Left, TextAlign.Right, TextAlign.Right])
);

Colspan cells — merge columns in footer or data rows:

using PdfScript.Core;

.SetFooter(
    [ColspanCell.Encode(3, "Total Amount:"), "$85,976"],
    [TextAlign.Right, TextAlign.Right]
)

Full Fluent Example

using PdfScript;
using PdfScript.Core;

byte[] pdf = new PdfDocumentBuilder()
    .SetTitle("Q1 2026 Sales Report")
    .SetAuthor("Finance Team")
    .SetSubject("Quarterly Sales")
    .SetKeywords("sales quarterly finance")
    .SetPageSize(PageSize.A4)
    .SetLandscape(false)
    .SetMargin(Margin.Normal)
    .SetWatermark("DRAFT", intensity: 0.10f)

    // Page 1 — Summary
    .AddHeading("Q1 2026 Sales Report", 1)
    .AddParagraph("Revenue grew by **42%** year-on-year with strong results across all regions.")
    .AddSpacer(10)

    .AddBox(
        b => b.AddParagraph("**Highlight:** Best quarter in company history."),
        background: PdfColor.FromHex("#eef8ff"),
        border:     PdfColor.FromHex("#99ccff")
    )
    .AddSpacer(10)

    .AddTable(t => t
        .AddColumn(ColSpec.Auto)
        .AddColumn(ColSpec.Star())
        .AddColumn(ColSpec.Fixed(80))
        .AddColumn(ColSpec.Fixed(80))
        .SetHeaderBackground(PdfColor.DarkBlue)
        .SetHeaderForeground(PdfColor.White)
        .SetEvenRowBackground(new PdfColor(0.93f, 0.96f, 1f))
        .SetRepeatHeader(true)
        .SetHeader("Region", "Manager", "Target", "Actual")
        .AddRow("North", "Alice Johnson", "$50,000", "$61,200")
        .AddRow("South", "Bob Smith",     "$45,000", "$48,750")
        .AddRow("East",  "Carol White",   "$55,000", "$59,900")
        .AddRow("West",  "David Lee",     "$40,000", "$38,200")
        .SetFooter(
            [ColspanCell.Encode(2, "Total"), "$190,000", "$208,050"],
            [TextAlign.Right, TextAlign.Right, TextAlign.Right]
        )
    )

    // Page 2 — Notes
    .AddPageBreak()
    .AddHeading("Notes", 2)
    .AddParagraph("All figures are in USD. Targets were set in January 2026.")
    .AddRule()
    .AddParagraph("*Report generated by PdfScriptCompiler*", TextAlign.Center)

    .Build();

File.WriteAllBytes("q1-report.pdf", pdf);

Method 3 — Compile from String

Use PdfScriptCompiler.Compile() to compile a PDFScript markup string directly to a byte[].

using PdfScript;

string source = """
    @page a4
    @title "Hello World"

    # Hello World

    This PDF was generated from a C# string literal.
    """;

byte[] pdf = PdfScriptCompiler.Compile(source);
File.WriteAllBytes("hello.pdf", pdf);

This is the lowest-level API — useful when you generate markup dynamically (e.g., from a template engine or user input).


Method 4 — Compile from File

Use PdfScriptCompiler.CompileFile() to compile a .pdfs file on disk.

using PdfScript;

// Output defaults to same path with .pdf extension
PdfScriptCompiler.CompileFile("report.pdfs");
// → writes report.pdf

// Specify a custom output path
PdfScriptCompiler.CompileFile("report.pdfs", "/output/report.pdf");

Throws FileNotFoundException if the input file does not exist.


Method 5 — Compile to Stream

Use PdfScriptCompiler.CompileToStream() to write PDF bytes directly to any Stream.

using PdfScript;

// Write to a MemoryStream
using var ms = new MemoryStream();
PdfScriptCompiler.CompileToStream(source, ms);
byte[] bytes = ms.ToArray();

// Write directly to a FileStream
using var fs = new FileStream("output.pdf", FileMode.Create);
PdfScriptCompiler.CompileToStream(source, fs);

No intermediate byte array is created — the PDF is written directly to the stream. Ideal for HTTP responses.


Encryption

PdfScriptCompiler uses RC4-128 / PDF Standard Security Rev 3, compatible with Acrobat 5+, Adobe Reader, Foxit, Chrome, and all modern PDF viewers.

Markup

@encrypt userpwd="open123" ownerpwd="admin456" permissions=all
permissions value Effect
all Full access (default)
readonly Print only — no modify, copy, or extract
none No permissions granted

Fluent API

// Full access with passwords
.SetEncryption(EncryptionSettings.PasswordProtect("open123", "admin456"))

// Print-only (read-only)
.SetEncryption(EncryptionSettings.ReadOnly("view", "admin"))

// Custom permission flags
.SetEncryption(new EncryptionSettings
{
    UserPassword  = "user",
    OwnerPassword = "admin",
    Permissions   = PermissionFlags.Print | PermissionFlags.FillForms
})

PermissionFlags reference

PermissionFlags.Print         // allow printing
PermissionFlags.Modify        // allow content modification
PermissionFlags.Copy          // allow text copying
PermissionFlags.Annotations   // allow adding annotations
PermissionFlags.FillForms     // allow filling form fields
PermissionFlags.Extract       // allow content extraction
PermissionFlags.Assemble      // allow page assembly
PermissionFlags.PrintHighQual // allow high-quality printing
PermissionFlags.All           // all permissions
PermissionFlags.None          // no permissions

Watermarks Reference

A watermark is drawn behind all content on every page of the document.

Markup

@watermark text="DRAFT" opacity=0.12 angle=45 fontsize=80

Fluent API

.SetWatermark(
    text:      "CONFIDENTIAL",
    intensity: 0.12f,   // 0 = invisible, 1 = solid black
    angleDeg:  45f,     // degrees counter-clockwise
    fontSize:  80f      // pt
)

Common presets

Use case text intensity angle
Draft document "DRAFT" 0.12 45
Confidential "CONFIDENTIAL" 0.10 30
Sample / demo "SAMPLE" 0.18 45
Horizontal stamp "APPROVED" 0.12 0
Dark visible mark "INTERNAL" 0.35 45

Colors

Colors are expressed as PdfColor with RGB values between 0 and 1, or created from hex strings.

// Named constants
PdfColor.Black
PdfColor.White
PdfColor.Gray
PdfColor.LightGray
PdfColor.Silver
PdfColor.Blue
PdfColor.DarkBlue
PdfColor.Navy
PdfColor.Red
PdfColor.Green
PdfColor.Orange

// From hex string
PdfColor.FromHex("#1a3a6b")
PdfColor.FromHex("#eef3ff")
PdfColor.FromHex("#f0c060")

// From RGB floats (0.0–1.0)
new PdfColor(0.1f, 0.4f, 0.85f)

In markup, colors are always specified as #rrggbb hex strings:

headerbg=#1a3a6b
headerfg=#ffffff
bg=#eef3ff
border=#99aadd
[color=#cc0000]text[/color]

Page Sizes and Margins

Page sizes

Constant Dimensions (pt) Common use
PageSize.A4 595 × 842 Standard international
PageSize.Letter 612 × 792 US standard
PageSize.A5 420 × 595 Half A4, booklets
PageSize.Legal 612 × 1008 US legal documents
PageSize.A3 842 × 1191 Wide format, posters

Landscape swaps width and height:

.SetPageSize(PageSize.A4).SetLandscape(true)   // 842 × 595 pt

Margins

Constant Values (pt) Use
Margin.Normal 60 / 50 / 60 / 50 Default — balanced
Margin.Narrow 36 all sides Dense tables, forms
Margin.Wide 72 all sides Formal documents
Margin.All(v) v all sides Custom uniform
Margin.Symmetric(v, h) vertical / horizontal Custom symmetric
new Margin(top, right, bottom, left) all four Full custom

In markup:

@margin 60 50 60 50    // top right bottom left
@margin 36             // all sides
@margin 60 50          // vertical horizontal

ASP.NET Core Integration

Return a PDF directly from a controller or minimal API endpoint:

// Minimal API
app.MapGet("/report", () =>
{
    string source = """
        @page a4
        @title "Live Report"
        # Live Report
        Generated on demand by ASP.NET Core.
        """;

    byte[] pdf = PdfScriptCompiler.Compile(source);
    return Results.File(pdf, "application/pdf", "report.pdf");
});

// MVC Controller
[HttpGet("invoice/{id}")]
public IActionResult GetInvoice(int id)
{
    var source = BuildInvoiceMarkup(id);
    Response.ContentType = "application/pdf";
    PdfScriptCompiler.CompileToStream(source, Response.Body);
    return new EmptyResult();
}

// Stream directly to response (no byte[] allocation)
app.MapGet("/stream", async (HttpResponse response) =>
{
    response.ContentType = "application/pdf";
    PdfScriptCompiler.CompileToStream(source, response.Body);
});

License

MIT © 2026 AB21RAM — see LICENSE for full text.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.2.0 100 5/5/2026
2.1.0 101 5/2/2026

v2.2.0
     - Watermark support: @watermark directive and SetWatermark() fluent API
       (text, intensity 0–1, angle, font size — all configurable)
     - Table last-row bottom border fix (was missing in v2.1)
     - Box layout: padding increased to 14pt; background rect no longer clips
       tall content; oversized boxes no longer overflow bottom margin
     - HRule spacing increased (SpaceY 8→12pt) for better breathing room
     - Package icon added (visible in nuget.org and VS/Rider package manager)
     - Expanded NuGet tags and keyword-rich description for better search ranking
     - PdfScriptTest project: 100-PDF test suite covering all APIs

     v2.1.0
     - Landscape orientation support
     - RC4-128 encryption with user/owner passwords and permission flags
     - Smart table columns: fixed, star, auto widths with cell text wrapping
     - Per-cell alignment (colon syntax)
     - Fluent PdfDocumentBuilder + TableBuilder API
     - Symbols package (.snupkg) for step-through debugging