Skip to content

Papercut 0.6.0

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 01 Nov 09:09
· 86 commits to main since this release

Added

  • Laravel: a PendingOutput or PendingHtml can be attached to a mailable or notification with ->attach(...). The document renders when it is attached, and the attachment is named document.pdf, document.docx or document.html. PendingOutput::attachment('name.pdf') sets the name (cleaned like download()) without rendering; PendingHtml attaches the full page. PapercutManager, PendingDocument, PendingOutput and PendingHtml are Macroable.
  • Span::code($text) and Text::code($text): inline code in PHP, a literal span in the code style, the same as <x-doc::code> and <code> in markup.
  • PHP setters that take an option also take its string value, matched without regard to case or surrounding spaces: direction, justify and align on View, Row and Column; alignSelf, textAlign and the style argument of border; TableCell::align, Image::fit, ListNode::marker, Place::anchor, and QrCode::make (the level), errorCorrection, shape, eyes and gradient (the type). A case name also matches, so 'high' is ErrorCorrection::High. ->align('center') now works as in Blade; an unknown string throws InvalidValue with a suggestion.
  • Other names for the anchors in the middle of each side: top-center, bottom-center, center-left and center-right as strings and in Blade's anchor, and Anchor::TopCenter, Anchor::BottomCenter, Anchor::CenterLeft and Anchor::CenterRight in PHP. They are the same cases as Top, Bottom, Left and Right. <x-doc::place anchor> now also ignores case and suggests the closest name for a typo.
  • A guide example (examples/core/documents/guide.php and examples/laravel/views/guide.blade.php): a three-page API integration guide on US Letter, portrait then landscape then portrait, with syntax-highlighted code blocks, badges in a table, a QR code and a go-live checklist.
  • A certificate example (examples/core/documents/certificate.php and examples/laravel/views/certificate.blade.php): a name, course, date and signature image placed on a blank US Letter landscape PDF template, built by examples/core/certificate-template.php. It is PDF only, because Word and HTML exports leave page templates out.
  • An article example (examples/core/documents/article.php and examples/laravel/views/article.blade.php): a two-page knowledge base article on A4, made from the HTML a rich text editor saves, with PDF, HTML and Word output.
  • Tables of contents: Toc::make()->levels(1, 3)->title('Contents')->leaders(false) in PHP and <x-doc::toc levels="1-3" title="Contents" :leaders="false" /> in Blade. Entries are the h1 to h4 headings (default levels 1 to 2), each with its physical page number and dot leaders, and a link to the heading in the PDF. ->toc(false) / toc="false" leaves a heading out; bookmark('Short') sets the entry's text and bookmark($title, $level) its level. Styled by the named styles toc, toc.title, toc.entry and toc.level-1 to toc.level-4. Word export writes a real TOC field filled in with the PDF's page numbers (Update Field in Word renumbers it; an updated field reads Heading 1 to 4, so toc(false) and bookmark levels aren't honoured then), and runs the PDF layout for documents that have one (if that layout can't run, the field is written without page numbers and the export still succeeds). HTML export writes a <nav class="papercut-toc"> of links without page numbers, reported as approximated. A table of contents in a header, footer, background or overlay throws InvalidStructure.
  • The report example has a table of contents (PDF, Word and HTML outputs regenerated).
  • Laravel: PendingOutput::streamDownload('name.pdf') returns the download as a streamed response, named like download(), that renders the document when it is sent. Livewire actions, and so Filament actions, send files only from streamed or file responses, so download() does nothing there and streamDownload() works.
  • A Laravel recipes page in the docs: storing on S3 or any disk, making documents in a queued job, emailing them, downloading from Livewire or Filament, and drawing charts as SVG from a Blade component.
  • Theme overrides per document and per page. In PHP, Document::theme(new ThemeOverride(...)) and Page::theme(...) set font family, size, weight, colour, line height, cell padding, minimum lines, mono family, code theme and named styles for one document or page; Theme::withOverride() does the merge. In Blade, <x-doc::document :theme="[...]"> and <x-doc::page :theme="[...]">; PendingDocument::theme([...]) from a controller. Order: config, the view's document, the controller, then the page. Named styles in an override merge onto the existing style. PDF lays out each page with its theme, HTML writes the page's differences on its section, and Word writes the document theme as Word's defaults and page values on that page's paragraphs.
  • Named styles h1 to h4 style headings of that level at every theme level (Theme::withStyle(), papercut.styles, overrides). Layering: the built-in heading look, the theme's h<n> style, the node's own style name, then its own style.
  • A page or document code theme (codeTheme in PHP, code_theme in Laravel) is the default for code blocks that don't name a theme.

Changed

  • Laravel: unknown keys in papercut.theme now throw instead of being ignored. Only font_family, mono_family, font_size, color and line_height are read there; the error names the key and points code_theme to papercut.code.theme and styles to papercut.styles.
  • Breaking: a custom style named h1, h2, h3 or h4 now applies to headings of that level. Without one, headings look as before.
  • Word export (papercut/docx) is no longer labelled experimental. It is versioned with core and Laravel, and follows the same compatibility rules. Word, LibreOffice and Google Docs still lay out the file themselves, so page breaks can differ from the PDF.
  • Breaking: Spacer::size($length) is now Spacer::fixed($length). The static factory hid the size() modifier every other node has, so $spacer->size(pt(9)) quietly made a new spacer and dropped its grow and background. On a spacer, ->size() now sets the gap and keeps the rest of its style. Blade's <x-doc::spacer size="..."> is unchanged.
  • Custom Backend implementations must handle the new Papercut\Paint\Anchor op. It draws nothing and marks a named destination for a table of contents entry; it only appears in documents that have a table of contents.
  • InvalidStructure moved to core as Papercut\Exception\InvalidStructure. Papercut\Laravel\Exception\InvalidStructure now extends it, so existing catch blocks keep working.
  • The guide example uses Text::code() for inline code and one string option (->align('center')).
  • The docs say that columns() accepts any length unit, and list the code block language aliases (bash, sh, shell and zsh for shell, js, ts, py, yml).
  • The README, the Laravel package description and the social preview image name all three formats (PDF, Word, and HTML); core's description names PDF and HTML. The guide's limitations say "fillable form fields (AcroForms)" instead of "form filling", since filling in an existing PDF works, and the HTML export page says backgrounds and overlays are approximate.
  • The invoice and transcript examples use US Letter and inches instead of A4 and millimetres, so the examples show both (the report and form responses stay on A4). The transcript now runs to three pages.

Fixed

  • Invisible formatting characters (soft hyphens, zero-width joiners and spaces, direction marks, word joiners, byte order marks), common in text pasted from Word or a CMS, are no longer drawn as empty boxes in PDF. The line and paragraph separators (U+2028, U+2029) count as newlines.
  • Strict mode throws UnsupportedFeature when a printed page of a PDF has characters no font has, in text or SVG text, naming the page and the characters. They print as empty boxes, and before only a warning said so, which plain PHP drops unless you pass onWarning. The fonts guide has a new section on fallback fonts for names in other scripts, and says that a short right-to-left run, such as an Arabic or Hebrew name, already lays out correctly.
  • Content taller than its box's height or max-height no longer draws over what follows without a word. It follows the overflow mode, as content too tall for a page does: Throw mode throws LayoutOverflow naming the box, and Clip mode clips it to the box and warns. Documents whose boxes overflowed now throw in Throw mode (Laravel's default in local and testing) or come out clipped.
  • papercut/laravel and papercut/docx require papercut/core ^0.6 (and Laravel's dev requirement on papercut/docx is ^0.6); they still asked for ^0.5, which no 0.6 core satisfies.
  • A release candidate tag (v1.0.0-rc.1, any version with a -) is published as a GitHub pre-release.
  • A table row too tall for one page, split just below the header, no longer paints its first line past the bottom of the page when that line doesn't fit below the header. This includes rows with spanning cells and tables inside table cells. A repeated header is left out on that page instead; on the first page the header stands alone and the rows start on the next page, with a warning.