Releases
Changelog
Every version of @ngpdf/core, newest first. Each one is published from GitHub Actions with npm provenance, and its GitHub release carries an SBOM.
1.0.1
Patch Changes
- #300
ee94df9Thanks @GabeSilvaDev! - The npm README now describes 1.0 instead of v0.1. It explains when a tall table row or rowpdf-viewcontinues onto another page and when it is clipped, and it links to the current roadmap.
1.0.0
Major Changes
- #298
8863c68Thanks @GabeSilvaDev! - First stable release. From 1.0 on, the public API follows semantic versioning: breaking changes to the elements, their inputs, the style properties,PdfRendererand the server entry point only come in a new major version. Nothing breaks in this release by itself; it groups the v1.0 features listed below (pdf-svg, pages that grow with their content, row views that split across sheets,min-presence-ahead, every standard paper size and page sizes with units).
Minor Changes
#294
43c733eThanks @GabeSilvaDev! -pdf-pagetakesautoas its height, for receipts and other slips with a fixed width:[size]="[226, 'auto']",['80mm', 'auto']orsize="80mm auto". Each sheet is as tall as its content plus the page's padding and border, with bottom fixed views and the page number right after the content. A page break you ask for starts a new sheet sized to its own content. A sheet grows to at most 14400pt; taller content breaks onto more sheets, with a development-mode warning.autoas the width, ororientation="landscape"with an auto height, throws.#290
a510921Thanks @GabeSilvaDev! - New style propertymin-presence-ahead, to keep a section title from sitting alone at the bottom of a sheet. Set it to a length, for examplemin-presence-ahead: 80pt, and an element that would leave less than that much space below it on its sheet moves to the next one. The space is measured above the page number and fixed footers. An element already at the top of a sheet, the last one on apdf-page, or one followed by a page break (break-after: pageon it orbreak-before: pageon the next element) stays where it is. It works on texts, images, views, tables and table rows (a value on a cell counts for its row); a header row ignores it. Elements joined to a moved element withbreak-after: avoidmove with it. The default0changes nothing; a percentage, a keyword or a negative length throws.#291
9a9b5e5Thanks @GabeSilvaDev! -pdf-pagesizenow takes lengths as well as points. Each side of[width, height]can be a number of points or a length string inpt,px,in,cmormm, as in styles:[size]="['210mm', '297mm']". One number or length makes a square page ([size]="400",size="400",size="10cm"), and the CSS@pageform with two lengths works too:size="210mm 297mm".%,em,autoand other units, a side that is zero, negative or not finite, and a string with more than two lengths fail withngpdf: unknown page size "<size>" on pdf-page. A pair with more than two values, which was cut to its first two, now fails the same way.orientation="landscape"still always swaps width and height, for these sizes as for names.#289
ef6cd86Thanks @GabeSilvaDev! -pdf-pagesizenow knows every standard paper size, so a label on A6, a book on B5 or an envelope on C5 no longer needs its points worked out by hand: ISO A0 to A10, B0 to B10, C0 to C10, 2A0 and 4A0, RA0 to RA4 and SRA0 to SRA4, the Japanese B series asJIS-B0toJIS-B10, and the US sizesExecutive,Folio,Tabloid,LedgerandID1. All of them are portrait;orientation="landscape"turns them.Ledgerfollows CSS Paged Media and is the same 11 × 17 in sheet asTabloid, so the traditional landscape ledger issize="Ledger" orientation="landscape". Size names now match in any case at run time, sosize="a4"no longer throws; thePageSizetype keeps the spellings from the docs table. The existing sizes keep the same points, and an unknown name still fails withngpdf: unknown page size "<size>" on pdf-page.#292
9121583Thanks @GabeSilvaDev! - Addpdf-svg, which draws an SVG as vector shapes wherever apdf-imagecan go. Itssrctakes SVG markup, adata:image/svg+xmlURL, an http(s) URL (read like an image URL, withmaxImageBytesand the server'sfetchImagerule) or aBlob. It is sized like an image from the SVG'swidth,heightandviewBox, honourspreserveAspectRatio, and is clipped to its box. It drawssvg,g,path(the wholedgrammar, arcs included),rect,circle,ellipse,line,polyline,polygon,usewithin the same file, and linear and radial gradients, with fills, strokes, dashes, opacity,visibility, the six transform functions andcurrentColor, which is the element's owncolor. Text, images, clip paths, masks, filters, patterns, markers and<style>sheets are left out with one development-mode warning each. The parser is ngpdf's own, so it works the same on the server: it reads no DTD or external entities, runs no scripts, fetches no external references, and throwsngpdf: pdf-svg …past 1 MB of source, 50,000 elements, 64 levels of nesting, 16 levels ofuseor 1,000,000 path segments, gradient stops, dashes and attributes drawn. Malformed markup throwsngpdf: invalid SVG: <reason> at <offset>.#295
405689eThanks @GabeSilvaDev! - A rowpdf-view(or blockpdf-link) taller than a page now splits across sheets instead of being cut at the bottom, so a two-column layout with a long main column runs over as many pages as it needs. It splits the way a tall table row does: each child breaks on its own, apdf-textbetween its lines and a columnpdf-viewbetween its children, and each piece is as tall as its tallest child piece. The row's background and border are sliced per sheet with no border drawn at a cut, and a child stretched to the row's height, such as a shaded sidebar, fills every piece. A row view that fits on a page still moves to the next one whole, so documents that already fit keep their pages.break-inside: avoid, a fixedheightormax-height, atransformor anoverflowother thanvisiblekeep the old behaviour: one unit, cut at the bottom with the dev-mode warning. A single line of aflex-wrap: wraprow that is taller than a page now splits the same way.#296
277daefThanks @GabeSilvaDev! -pdf-svgdrawssymbol, so icon sprites made of<symbol>and<use href="#id">now show up instead of drawing nothing with a warning. Asymbolis drawn only through ause, as a nestedsvg: itsviewBoxandpreserveAspectRatioapply, it is placed at theuse'sxandyand clipped to theuse'swidthandheight, or else thesymbol's own, or else 100% of the drawing around it, skipping a negative size. The limits onusecount eachsymboldrawn: 16 levels deep, 50,000 elements and the drawing budget.
Patch Changes
- #297
21566d8Thanks @GabeSilvaDev! - Apdf-svgorpdf-canvaswith a huge but finite number no longer crashes the render with pdfkit's bareunsupported numbererror. Every number a drawing writes now stays within ±1e9 (about 350 km of page). Past that, apdf-svgfails withngpdf: pdf-svg <rect> has the number 1e+22, past ±1e9, naming the element, and apdf-canvaswithngpdf: pdf-canvas fill has the number …, past ±1e9, naming the paint call. This covers path coordinates, shape sizes, stroke widths, dashes, gradient coordinates, transforms and aviewBoxfitted at a huge scale. Each number is checked in its own coordinates, so a large drawing scaled down onto a page still renders. The writer checks every drawing operation, page size and gradient again before pdfkit sees it.
0.9.0
Minor Changes
#281
e70c53fThanks @GabeSilvaDev! -dashedanddottedborders are now drawn as dashes and dots instead of solid lines with a warning. Dashes are 3 times the border width long and dots are as wide as the border, about 2 widths apart, with the gaps fitted so each side starts and ends at its corners. A rounded box with four alike dashed or dotted sides is drawn as one outline, so the pattern runs on round the corners.border-style(1 to 4 values) andborder-top-style,border-right-style,border-bottom-styleandborder-left-styleset the style per side; before, they were ignored. A side whose style isnoneorhiddennow has a width of 0 whatever order the declarations come in, soborder: none; border-width: 2no longer draws a border.double,groove,ridge,insetandoutsetare still drawn solid with a warning.#275
0c7ad77Thanks @GabeSilvaDev! -display: nonenow hides an element. It leaves the element and everything inside it out of the document: it takes no space, starts no new sheet and draws nothing, and the fixed views, absolute elements, notes, images and bookmarks inside it go with it. An anchor inside a hidden element does not exist, so apdf-linkto it gets the "names no anchor" warning in development mode and is drawn without a link. You can now write[style.display]="shown() ? null : 'none'"where you needed@if.display: flexis the default and still accepted. Any other value, such asblockorgrid, now throwsngpdf: invalid value "block" for display on pdf-view; use flex or none. It used to be ignored without a warning.#287
286273dThanks @GabeSilvaDev! - Rows can wrap. Newflex-wrap(nowrap,wrap,wrap-reverse), theflex-flowshorthand (<direction> <wrap>, either part optional, the missing one reset to its default as in CSS) andalign-content(stretchby default,flex-start,center,flex-end,space-between,space-around,space-evenly). These properties used to be ignored silently; a bad value now throws. Each line of a wrapping row is its own unit for pagination, so a long grid of cards or tags breaks between its lines and never through one, and the row gap before a line moved to a new page is dropped.align-contentis not redone per page: lines keep their places from the single layout. A column withflex-wrapwhose children went into several columns is kept whole.flex-wrapon apdf-rowinside a table is ignored, with thengpdf: ignored inside tables: pdf-row flex-wrapdevelopment-mode warning.#279
526e619Thanks @GabeSilvaDev! -font-weightnow takes any number from 1 to 1000 and the namesthin(100),extralight(200),light(300),normal(400),medium(500),semibold(600),bold(700),extrabold(800) andblack(900), andbolderandlighterfollow the CSS table from the inherited weight.providePdfFontstakes a numericweightper face, so a family registered with Light, Medium or Black faces can use them;'normal'and'bold'still work as 400 and 700. When a family has no face for a weight, ngpdf picks one as CSS font matching does, and the development warning names the face it drew with.Two things change for existing documents. An unknown
font-weightvalue such asheavyused to draw normal text and now throwsngpdf: invalid value "heavy" for font-weight on <element>, with the allowed values in the message. The standard fonts are drawn bold above 500 rather than from 600, which only changes numbers between 501 and 599.#282
dc17963Thanks @GabeSilvaDev! - Text now sits in the middle of its line, as in CSS: the extra space thatline-heightadds is split in half above and below the text (half-leading), where it used to go all below it. Text in a box with a largeline-heightmoves down; with the defaultline-height: 1.2, Helvetica moves down by about 0.14 of its font size. Aline-heightsmaller than the font's height moves text up. Line heights, box sizes and page breaks do not change, a link's clickable area still covers the whole line, and underlines and strike-throughs follow the text. In a line with spans of several sizes, the span that reaches highest sets the baseline. The page number is placed the same way.#285
a1e7688Thanks @GabeSilvaDev! - Every style property that takes keywords now throws on one it doesn't know. Before,font-styledrew an unknown value asnormal, andbreak-before,break-afterandbreak-insideignored theirs; now they throw like the others.font-styletakesnormal,italicoroblique,break-beforetakesautoorpage,break-aftertakesauto,page,avoidoravoid-page, andbreak-insidetakesauto,avoidoravoid-page, in any case. Sobreak-before: always,break-after: column,break-inside: avoid-columnorfont-style: oblique 10degnow fail the render. The message names the value, the property, the element and the keywords the property takes, for examplengpdf: invalid value "middle" for text-align on pdf-text; use left, center, right or justify, and properties that already threw (text-align,display,border-style,white-space,text-overflow,flex-wrap,align-contentand the rest) now list their keywords the same way.flex-flowandvertical-alignend their message with what they take, for exampleuse baseline, super, sub, a length or a percentage.border-styleerrors used to readinvalid border style "<value>". Unknown properties are still ignored.#277
473b4a5Thanks @GabeSilvaDev! - Apdf-viewwithfixed="top"orfixed="bottom"now takes its ownwidthand places itself withautoleft and right margins, sowidth: 200; margin: 0 autocentres a header andmargin-left: autopushes a footer to the right. A fixed view used to be laid out at the full content width less its margins whatever itswidth, so a document that setswidthon one now draws it at that width. In the flow,automargins already worked through Yoga, and the docs now say so:margin: 0 autocentres a box with a width,margin-left: autopushes a row item to the end, and a box withmargin-top: autoin a column split across sheets keeps the position it had in the unsplit layout.#280
b40fdfdThanks @GabeSilvaDev! -pdf-pagetakes adpiinput (72 by default) for documents made for print at a given resolution. An image on that page with nowidthand noheightnow takes 72 /dpipoints per pixel, so a 600-pixel image on adpi="300"page is 2in wide. This includes images in fixed views andpdfPerSheetcontent. Images with a size set keep it,pxin styles stays 1pt, and the page keeps its size in points, so viewers show it at its real size. Adpithat is not a finite number above 0 throwsngpdf: invalid dpi "<value>" on pdf-page.#276
b14035dThanks @GabeSilvaDev! - Newrow-gapandcolumn-gapproperties, andgapnow takes two values,gap: <row> <column>. One value still sets both. Gaps take any length unit ngpdf accepts or a percentage of the container's content box (its height forrow-gap, its width forcolumn-gap);gap: 10%used to throw. A negative gap throws. On apdf-rowinside a table only the column gap is ignored, and the development-mode warning now namespdf-row column-gapinstead ofpdf-row gap; arow-gapthere no longer warns.#286
d6dffdfThanks @GabeSilvaDev! -pdf-texttakestext-overflow: clip | ellipsis. Withellipsisand a fixedheightormax-heighton the samepdf-text, it keeps the lines that fit in its content box. When text was cut, the last kept line ends with…, cut the waymax-linescuts it. Withmax-linestoo, the smaller number of lines wins. When not even one line fits, the first line is kept, ending with…when more text follows it.clipis the default and keeps the old behaviour. The property is not inherited, and anoverflow: hiddenparent's height does not count.#283
109e6d0Thanks @GabeSilvaDev! - Apdf-spannow takesvertical-align: baseline | super | sub | <length> | <percentage>for superscripts and subscripts such as m², H₂O and footnote markers.superraises the span by 0.33em andsublowers it by 0.2em of the font size around it, and both draw it at 70% of that size unless the span sets its ownfont-size. A length raises the text by that amount (negative lowers it) and a percentage is of the span's line height; neither changes the size. A nested span moves with the span around it. A line grows when a moved run sticks out of it, and the underline, strike and link area of the span move with its text.vertical-alignused to be ignored everywhere; on an element other than apdf-spanit is still ignored, now with a development-mode warning, and a keyword such asmiddlethrows.#284
3638f15Thanks @GabeSilvaDev! - Newwhite-spaceproperty:normal(the default, unchanged),nowrap,pre,pre-lineandpre-wrap, inherited and allowed onpdf-span, as in CSS. Withpre-line, an address or note bound from data keeps its line breaks:<pdf-text style="white-space: pre-line">{{ address }}</pdf-text>.preandpre-wrapalso keep spaces, and tabs go to stops every 8 spaces.nowrapandpredo not wrap, and a line wider than its box overflows it.white-spacewas ignored before.
Patch Changes
- #288
fa88de8Thanks @GabeSilvaDev! - In apdf-tablewithflex-direction: row, where the header rows sit beside the body rows, a fixedrow-gaporgapno longer pushes a body row below its header. A row split across sheets now starts each piece beside the repeated header, at the header's top, as a percentagerow-gapalready did. When the header is taller than the room left on a sheet, the rows beside it move to the next sheet with it, so the header is not cut at the bottom.
0.8.0
Minor Changes
#273
654893fThanks @GabeSilvaDev! - AddsVERSION, the version of@ngpdf/coreyour app runs, as an AngularVersionwithfull,major,minorandpatch(the same shape asVERSIONfrom@angular/core). Import it from@ngpdf/coreto put the version in bug reports, support tools or your ownproducer. The version isn't added to the defaultproducer, which staysngpdf, so upgrading doesn't change the bytes of a PDF rendered with a fixedcreationDate.#269
6674be4Thanks @GabeSilvaDev! - AddsmaxImageBytes, a render option next toinputsthat caps the size of images fetched from a URL. A response whoseContent-Lengthis over the cap is refused before its body is read; otherwise the download stops as soon as the bytes read pass the cap, and the render rejects withngpdf: could not load image "<url>": larger than N bytes.PdfRenderer,renderToBlob,downloadPdf,pdfResourceandrenderToBuffertake it,PdfDownloadtakespdfMaxImageBytesandpdf-viewertakesmaxImageBytes. On the server it checks whatfetchImagereturns. Data URLs and bytes are not counted. There is no cap by default.#268
753b761Thanks @GabeSilvaDev! - AddspdfPerSheet, for content in a fixed header or footer that changes from sheet to sheet, such as "Continued on next page" on every sheet but the last and "End of report" on the last. Put<ng-template pdfPerSheet let-sheet let-total="total">inside apdf-viewwithfixed="top"orfixed="bottom"; the template also getsfirst,lastandpage, thepdf-pagethe sheet comes from. It comes withPDF_ELEMENTS. The template renders like the rest of the document, with pipes, inputs and services, once per sheet. The view keeps the height of the template's content for a one-sheet document; content taller than that on a later sheet is cut and warns in development mode, so give the view aheightwhen its content varies. ApdfPerSheettemplate anywhere but inside a fixed view fails the render.
Patch Changes
#259
d0e857fThanks @GabeSilvaDev! - Absolute elements placed below the sheet that ends a page's content no longer get a sheet each. The first one starts a new sheet at its top, and the others land on that sheet, moved with it, until one's top falls below it and starts the next. Two badges with the sametopnow share one sheet instead of making two, and two elements one content height apart still land on two sheets.#272
ac7ce22Thanks @GabeSilvaDev! - A horizontal border line that crosses the bottom of the page in a unit taller than a page is now cut there. Before, its stroke could reach up to half its width below the content area, and a top border that started just above the cut was dropped.#263
906c78cThanks @GabeSilvaDev! - An accented letter written as a base letter plus a combining mark, such asefollowed by U+0301 (as macOS file names and some APIs send it), is now drawn as the composed letter (é) in the standard fonts instead of the letter followed by?, and no longer triggers the WinAnsi warning. In afont-familylist, a font that lacks the letter as written but has its composed form draws the composed form. A custom font that has the combining mark draws the text as before.#257
9308189Thanks @GabeSilvaDev! - A broken or cut-off PNG in apdf-imagenow rejects the render withngpdf: could not load image "<src>": the image data is corrupt or cut off. Before, a PNG with transparency whose pixel data was damaged made the render hang with an uncaught error. A damaged emoji image is drawn as text instead.#264
1eac6b4Thanks @GabeSilvaDev! - A line cut bymax-linesno longer ends in empty boxes when its last characters come from a font that has no…. The ellipsis is now drawn in the first font of thefont-familylist that has…, or...in the first one with.when none has…. A custom font that has…keeps drawing it itself, as before.#258
a7fc03dThanks @GabeSilvaDev! - Units that fill the content area exactly now stay on the sheet. Yoga's float32 rounding could put their bottom slightly past the page, by more on tall pages and with many units, which moved the last one onto an extra sheet. A unit may now end up to 1/131072 of the content height past the bottom (0.001pt at least). On every named page size a unit that is over by 0.01pt or more still moves.A table header that can't go on a page with the table's first row, because that row fits a page only without it and can't split, is now drawn once as ordinary rows, with a warning in development mode. It used to be left off that row's page, so a table with no row that fits under it lost its header entirely.
A table row that fits a page only without its header no longer has a piece cut at the bottom when no break in it fits below the header. It used to be split anyway, with the first piece drawn past the bottom of the sheet; it now goes whole on a sheet of its own, without the header and with a warning in development mode, and a header that can't go on a page with such a first row is drawn once, as above.
#262
f7c7156Thanks @GabeSilvaDev! - Styles that take a length, a number or an angle now accept exponent form, such as1e-7,1.5E3or1.2e-15pt. Numeric bindings write very small and very large values this way, so[style.left.pt]="Math.sin(Math.PI) * 10"or[style.opacity]="1e-7"now render instead of throwing. Anewith no digit after it is still part of the unit, so3emstill throwsunknown unit. A length or angle that is not finite, either as written (1e999) or once its unit is applied (1e308in,rotate(1e308turn)), throwsinvalid lengthorinvalid angle. A huge but finite gradient angle, such aslinear-gradient(1e308deg, red, blue), now renders in the direction of that angle modulo 360.#265
af0e7c9Thanks @GabeSilvaDev! - A JPEG with a stray byte between two segments now loads at its frame size, as it does in a browser. It used to fail the render withngpdf: invalid JPEG marker.#261
a375650Thanks @GabeSilvaDev! - A longhand such asmargin-topnow overrides an earlier shorthand such asmargin, as in a browser. Before,margin-top: 20; margin: 0; margin-top: 5gave a top margin of 0, and a[style.margin-top]binding lost to amarginin the staticstyle.#260
2d5c378Thanks @GabeSilvaDev! -break-before: pageon a repeated table header row, or on an element inside it, now starts a new page before the table's first row instead of being ignored. A table header that is not repeated because its rows are taller than a page together, or that is left off a page whose first row fits only without it, now warns in development mode.
0.7.0
Minor Changes
#149
20d2466Thanks @GabeSilvaDev! - Supportposition: relativeandposition: absolutewithtop,right,bottomandleft, as in CSS. A relative element is drawn moved by its offsets, and the layout around it does not change. An absolute element leaves the flow and is placed against the padding box of its nearest relative, absolute or transformed ancestor, or against the page's content area. Withleftandrightboth set andwidth: autoit stretches between them, and the same goes for the height. Positioned elements are drawn on top of the in-flow ones. An absolute element is never a pagination unit and is never split: it is drawn with its containing block when that is one unit, and otherwise on the sheet where its top lands.position: fixedandstickythrow; use thefixedinput ofpdf-viewfor a header or footer on every sheet.positionand the offsets are ignored onpdf-page,pdf-rowandpdf-cell. Before, all five properties were ignored.#151
0a14e4aThanks @GabeSilvaDev! - Adds links to places inside the document, and bookmarks. Give apdf-view,pdf-text,pdf-image,pdf-table,pdf-roworpdf-cellananchorname, and<pdf-link href="#name">jumps to it, for example from a table of contents. Abookmarktitle on the same elements adds an entry to the PDF's bookmarks panel, nested as the elements are nested in the template.pageModenow also takesUseOutlines, which opens that panel when the PDF opens. A link to a name that no element has, or a second element with the same name, draws the content as usual and warns in development mode.#142
254ecc9Thanks @GabeSilvaDev! -break-after: avoid(oravoid-page) keeps an element on the same sheet as what follows it, so a heading no longer ends a sheet alone in most cases. When the next unit does not fit, the element moves to the next sheet with it. For a split text, only its first lines need to fit. Several elements in a row withavoidmove together. An element already at the top of a sheet stays there, and a group that would not fit on an empty sheet is left where it is, so in those cases a heading can still end a sheet.#156
ea8bb74Thanks @GabeSilvaDev! - Addspdf-canvas, for charts, signature lines and other shapes. Put<pdf-canvas [paint]="draw" style="height: 120" />where apdf-viewcan go, and draw indraw(ctx, size)with lines, curves, rectangles, circles, ellipses and polygons, filled or stroked, with dashes, line caps and joins, colors, opacity and transforms. Coordinates are in points from the top left of the canvas's content box, and the drawing is clipped to it. The function runs once per render, after layout, with the canvas's final size, and a canvas in a fixed header or a repeated table header is drawn on every sheet. A canvas is never split across pages. A non-finite number, an unknown option, too many calls, an error thrown by the function or a function that returns a promise rejects the render with anngpdf: pdf-canvaserror. ThePdfCanvasContextandPdfCanvasPainttypes are exported.#157
b44817dThanks @GabeSilvaDev! - Adds adebuginput onpdf-documentthat draws layout outlines on every page, to find out why a box is not where you expect it. Each box gets a red outline around its border box, a blue dashed outline around its content box when it has padding or a border, and a small grey label with its tag and size in points. The page's content area gets a green dashed outline, and each line of apdf-texta thin grey one. The outlines are drawn on top of everything, follow transforms and are not cut byoverflow: hidden. Turningdebugon never changes the layout or where pages break. Each render with it on prints the dev-mode warningngpdf: debug outlines are on, so a debug PDF is not shipped by mistake.#161
9a54c47Thanks @GabeSilvaDev! - AddsprovidePdfEmoji, which draws emoji in color as small inline images. Give it a URL template such as'/emoji/{codepoints}.png', where{codepoints}becomes the emoji's code points in lower-case hex joined by-, without U+FE0F (1f44d-1f3fdfor 👍🏽), or a function that returns a PNG or JPEG for each emoji, ornullto leave it as text. Each emoji is 1 em square at the text's size, sits on the line like the letters around it, breaks lines as one character, takesletter-spacingand underlines, and works withmax-linesand justified text. ZWJ sequences, skin tones, flags and keycaps are drawn as one image.©,®,™and digits stay text on their own: they become emoji with U+FE0F after them, digits also in a keycap (with or without U+FE0F), and pictographic characters also in a ZWJ sequence or with a skin tone. Each distinct emoji is loaded once per render, and at most 500. An emoji whose image is missing, fails to load or takes more than 10 seconds is drawn as text with a warning in development mode, so it never fails the render. ngpdf ships no emoji images and fetches nothing unless you add the provider. An emoji image is not text, so it cannot be copied or searched, and color emoji fonts are still not supported.#150
44956d8Thanks @GabeSilvaDev! - Adds asecurityinput onpdf-documentto protect a PDF with a password and restrict what a viewer lets the reader do.userPasswordis asked for when the file is opened,ownerPasswordlifts the restrictions, andpermissionslimits printing to low resolution ('low') or turns it off ('none'), and turns off copying, modifying, annotating, filling forms, content extraction for accessibility or page assembly. Everything is allowed unless you turn it off. The file is encrypted with AES-256, with no new dependency. Restricting permissions without an owner password uses a random one, so the restrictions cannot be lifted. Permissions are only a request to the viewer and do not protect the content; the user password does. A password written in your app's code is visible to every user, so pass one the user typed or your server sent. A password longer than 127 bytes in UTF-8, as typed or after Unicode NFKC normalization, or a value of the wrong type, throwsngpdf: invalid security <field>.#146
b9e379bThanks @GabeSilvaDev! - Backgrounds can be gradients.background-imagetakes onelinear-gradient()orradial-gradient(), andbackgroundbecomes a shorthand for a color, a gradient, or both, with the color drawn under the gradient. Linear gradients take an angle (deg,rad,turn) ortoa side or corner; radial ones takecircleorellipse, a size keyword andat <position>. Stops take any supported color and an optional position in%or a length, spread and ordered as in CSS. The gradient fills the border box, followsborder-radius, and a view split across pages keeps one gradient for its whole height.repeating-*gradients,conic-gradient(),url()and several backgrounds throw anngpdf:error.#158
e122b9eThanks @GabeSilvaDev! -opacitynow fades an element and everything inside it as one picture, as in CSS. Before, each piece inside a faded view was faded on its own, so overlapping children showed through each other and a background showed through the text and borders drawn over it. Now a faded card looks like the same card, solid, made see-through as a whole. Content that doesn't overlap looks the same as before. A faded view inside another faded view still composes (0.5inside0.5is0.25over the page), a color's own alpha still applies, andopacity: 0hides the content while its links keep working. Each faded element adds a small object to the PDF; fonts and images inside are not embedded twice.#153
5ed8a06Thanks @GabeSilvaDev! - Adds hyphenation with the CSShyphensproperty:manual(the default),noneorauto. It is inherited, and apdf-spancan set it. A soft hyphen (­) in your text now marks a place where a long word may break, with a hyphen drawn at the end of the line; before, soft hyphens were dropped and words never broke there. Where the line does not break, a soft hyphen still draws nothing. Withhyphens: auto, words also break where your own hyphenation function allows: register it withprovidePdfHyphenation, for example on top of a pattern library you load lazily. ngpdf ships no hyphenation patterns.#148
bbf2e24Thanks @GabeSilvaDev! - Addspdf-link, which makes text or a box open a URL when a reader clicks it in a PDF viewer. Put<pdf-link [href]="url">around a block, or use it inside apdf-textfor inline text. Only absolutehttp:,https:andmailto:URLs become links. Any other URL, a relative or invalid one, or a missing one draws the content without a link and warns in development mode. A link does not change how the content looks. Apdf-linkinside anotherpdf-linkthrows an error.#155
3d7e4c3Thanks @GabeSilvaDev! - Addsng add @ngpdf/core, so you can start with one command instead of setting things up by hand. It installs the package and writes an example document to your application, ready to render. With--demo-routeyou also get a/pdf-demopage with a Download PDF button, so you can see a PDF in the browser right away.--projectpicks the application and--pathpicks the folder. Your existing files are never overwritten.#154
5ee6aa9Thanks @GabeSilvaDev! - Addspdf-note, a comment on the page that PDF viewers show as an icon opening a popup, like a sticky note. Put it where apdf-viewcan go, with the note's text as its content:<pdf-note author="Ana" icon="help">Is this before tax?</pdf-note>.authoris shown as the note's title,iconpicks one of the standard icons (commentby default,note,help,key,insert,paragraph,new-paragraph), andopenshows the popup when the file opens. The icon is sticky-note yellow unless the note sets its owncolor. A note takes no space in the layout and is not printed. Its icon sits where the next element starts, or anywhere withposition: absolute. A note in the flow lands on the same sheet as the content next to it; an absolute note follows the rules ofposition: absolute. The text can hold any character, also ones the page fonts can't draw. A note takes plain text only, and a note inside apdf-textfails the render.#143
7c94088Thanks @GabeSilvaDev! - Supportoverflow: hidden. An element's children, text and image are clipped to its padding box, with rounded corners when it hasborder-radius, so a card can crop anobject-fit: coverimage or long text. Its own background and border are not clipped.clip,scrollandautoclip likehidden, and the layout does not change. A columnpdf-viewor apdf-textthat clips, with any of the four keywords, is one pagination unit and is never split across pages. One taller than a page is cut at the bottom of that page, and the rest of it is not drawn on the next one.overflowis ignored onpdf-pageandpdf-table. Before,overflowwas ignored everywhere.#152
e11393fThanks @GabeSilvaDev! - Addspdf-viewer, a live preview of a document, from the new entry point@ngpdf/core/viewer.<pdf-viewer [document]="Invoice" [inputs]="{ invoice }" />shows the PDF in the browser's own PDF viewer and renders it again, after a 300 ms pause by default, wheninputschange. The previous PDF stays on screen while the next one renders. Content markedpdfViewerLoadingshows until the first PDF is there, and content markedpdfViewerErrorshows when a render fails;renderedandfailedemit the PDF and the error. Apps that don't import@ngpdf/core/viewerdon't bundle it. Chrome on Android shows no PDF inside a page and Safari on iOS shows only the first page, so offer a download next to the preview. If your Content-Security-Policy setsframe-src, allowblob:.pdfResource'surl()now keeps the previous PDF's URL while a newer render runs, instead of goingundefineduntil it finishes.#160
627d262Thanks @GabeSilvaDev! - Adds server rendering.renderToBufferfrom the new entry point@ngpdf/core/serverrenders a document to PDF bytes in Node, with no DOM: in a plain Node script, or in an Angular SSR route, where you can pass the app'sinjectorso the document uses its services. It takes the sameinputsasrenderToBlob, plusproviderssuch asprovidePdfFonts, and returns aUint8Arrayyou can send withres.end()or write to a file. Each call is isolated, so renders can run at the same time.renderToBufferfetches nothing by itself: anhttp:orhttps:image or font URL is read only through thefetchImagefunction you pass, and refused without it. Restrict that function to your own hosts; a URL from user data then cannot make your server request internal addresses. Relative URLs and other schemes, such asfile:, are refused on the server and never reachfetchImage. Data URLs and bytes work as before. On the server,downloadPdfandpdfResourcegiven aninjectornow throwngpdf: … needs a browserinstead of failing later. In an SSR page,pdf-viewershows its loading content and apdfResourcemade in a component stays idle; the browser renders the PDF.pdf-imagenow also takes aUint8Arrayassrc, so a NodeBufferfromreadFileworks as it is.#159
2dcf3e7Thanks @GabeSilvaDev! - A table row taller than a page now splits across pages instead of being cut off at the bottom. Each cell breaks on its own, between the lines of its text or between the elements of a columnpdf-viewinside it, and the header row repeats above every piece. The cells of every piece are as tall as each other, so their borders line up, and backgrounds and borders are sliced with no border drawn at a cut. Content that can't break, such as an image, moves whole to the next page, or is cut at the bottom when it is taller than a page. A split row draws its cells from the top, so vertical alignment inside it is ignored. Rows that fit on a page are placed as before.break-inside: avoidon a row keeps the old behaviour: the row is cut at the bottom of its page, with the development-mode warning.#145
168e1fbThanks @GabeSilvaDev! - Elements can now be rotated, scaled and moved withtransformandtransform-origin, as in CSS, without changing the layout around them. A transformed columnpdf-vieworpdf-textis kept whole on one sheet, and one taller than the sheet's content area is cut at the bottom of that area, with a warning in development mode.transformhas no effect onpdf-span,pdf-pageorpdf-table, andskew(),matrix()and 3D functions throw. See Transforms for the full syntax.
Patch Changes
#254
186c9c5Thanks @GabeSilvaDev! - A style property that only contains a side name, such asmargin-top-xorpadding-leftover, is now ignored like any other unknown property instead of setting that side.#244
8c42ff3Thanks @GabeSilvaDev! -line-height: normalis now matched in any case, like every other keyword:NORMALorNormalkeeps the inherited line height instead of failing the render.
0.6.0
Minor Changes
#139
376630bThanks @GabeSilvaDev! -letter-spacingandtext-transformare supported and inherited like the other text styles, also on apdf-span.letter-spacingadds space after each character and counts in wrapping, alignment andmax-lines.text-transformtakesuppercase,lowercaseorcapitalizeand is applied before the text is measured.#140
4d6e05dThanks @GabeSilvaDev! - Borders now followborder-radius.border-radiustakes one to four lengths in CSS corner order, and theborder-top-left-radius,border-top-right-radius,border-bottom-right-radiusandborder-bottom-left-radiuslonghands set one corner each. Radii too big for their box are scaled down together, as in CSS, and a view split across pages keeps square corners where the page cuts it. An elliptical radius (4 / 8), a percentage or a negative radius throws. Before,border-radiustook one length and rounded only the background, so square border lines stuck out of it.
0.5.0
Minor Changes
#133
76517d0Thanks @GabeSilvaDev! -breakAfteronpdf-viewandpdf-text, and the stylebreak-after: pageon any element but apdf-span, start a new sheet after that element. LikebreakBefore, it applies to a whole row when set inside one, and it never adds a blank sheet at the end of a page.break-inside: avoidnow works on a columnpdf-viewand apdf-tabletoo. One that doesn't fit in the space left on a sheet but fits on a whole sheet moves to the next sheet in one piece. One taller than a sheet splits as before.
Patch Changes
#132
0a5bad9Thanks @GabeSilvaDev! - Next line (U+0085) is now drawn as a normal space and collapses with the whitespace around it, like form feed, vertical tab and the line and paragraph separators. Before, a standard font drew it as?.#134
2d90fd2Thanks @GabeSilvaDev! - The style attribute is recognised in any case, as in HTML:[attr.STYLE]or a directive that setsStylenow styles the element instead of being ignored.#130
08afbf5Thanks @GabeSilvaDev! - Apdf-textsplit over several pages no longer leaves a page in the middle with fewer lines thanorphansandwidowsask for when its lines have very different heights. A page gives lines back to the one before it, or the text starts on the next page, when that keeps the limits. When no layout keeps them, lines are placed one by one as before.#129
dc34713Thanks @GabeSilvaDev! - Vertical tab, form feed and the line and paragraph separators (U+2028, U+2029) are now drawn as a normal space, and U+FEFF is removed. A standard font draws the ideographic space (U+3000) and the Ogham space mark (U+1680) as a space too, while a custom font that has them still draws its own glyph. Before, a standard font drew all of these as?in the middle of a line, while the same characters at the ends of a paragraph were trimmed as whitespace.
0.4.0
Minor Changes
#119
9844b8cThanks @GabeSilvaDev! - Add'auto'table columns:[columns]="['auto', '1fr', 'auto']"sizes a column to the widest content of its cells on one line, so codes, dates and totals fit without wrapping.autocolumns come after fixed and percentage columns and beforefrones, and shrink in proportion when they do not fit.#111
b2ac328Thanks @Aaqibhafeezkhan! - Add optional document language, application attribution and initial page-view preferences to generated PDFs. Language tags and viewer preferences are validated, and the PDF producer metadata now identifies ngpdf instead of PDFKit.#122
59006e9Thanks @GabeSilvaDev! - Addmax-linesto cut apdf-textto a number of lines. When text was cut, the last kept line ends with…, shortened until it fits the box, and the text is only as tall as the lines it keeps. A font without…gets...instead.#117
353ff5eThanks @GabeSilvaDev! -pdf-page-numbernow works anywhere in a page, not only as a direct child ofpdf-page. Put it in a fixed header to show "Page 2 of 5" on every sheet, or anywhere in the content to show the number of the sheet it lands on. A direct child ofpdf-pagestill reserves the bottom of every sheet as before.#121
6fb4354Thanks @GabeSilvaDev! - Addtext-align: justify. Every line of a paragraph but the last is stretched to both edges of its box by widening the gaps between words, acrosspdf-spans and across a page break. The last line, a line with one word and a word wider than the box stay at the start.
Patch Changes
#58
ced90e0Thanks @arxigen! - Style keywords are matched case-insensitively and trimmed, as in CSS.text-align: CENTERno longer throws, andfont-weight: BOLDandfont-style: ITALICare no longer dropped silently. This coverstext-align,text-decoration,flex-direction,justify-content,align-items,align-self,object-fit,font-weight,font-styleandbreak-before. Unknown keywords behave as before: they throw fortext-align,text-decoration,flex-direction,justify-content,align-items,align-selfandobject-fit, fall back tonormalforfont-weightandfont-style, and are ignored forbreak-before.#63
df2b007Thanks @arxigen! - ngpdf now uses pdfkit 0.20. pdfkit's ES module browser build replaces its old standalone bundle, so the combined PDF engine payload loaded on the first render drops from about 1.5 MB to about 610 KB before compression, and from about 433 KB to about 238 KB gzipped. The initial bundle is unchanged.The text and layout of the PDFs you get are unchanged. Their bytes are not: pdfkit 0.20 compresses streams with a different library and writes
/UserUnit 1on every page.A JPEG's EXIF orientation is now read the way pdfkit 0.20 reads it: from the first Exif segment before the image data, even when an XMP segment or a comment comes first. The image's laid-out size keeps matching how pdfkit turns it.
In an Angular CLI app, pdfkit no longer needs to be listed under
allowedCommonJsDependencies. Angular may now name fontkit's CommonJS dependencies instead (brotli,clone,dfa,fast-deep-equalandtiny-inflate).#60
82788a8Thanks @arxigen! - Large images given as percent-encoded data URLs load faster. The decoded image is unchanged.#56
af957f2Thanks @jay23606! - Supportthin,mediumandthickborder widths, and reject negative border widths.
0.3.0
Minor Changes
#116
1c7adcfThanks @GabeSilvaDev! - Add fixed headers and footers: apdf-viewwithfixed="top"orfixed="bottom", placed directly inside apdf-page, is drawn on every sheet of that page, and the content flows in the space between them. A footer sits above thepdf-page-number.#112
2e89379Thanks @GabeSilvaDev! - Add thepdf-spanelement to style part of a text, such as one bold word in a sentence:<pdf-text>Total: <pdf-span style="font-weight: bold">{{ total }}</pdf-span></pdf-text>. A span can change the color, font family, size, weight, style and decoration; the paragraph still wraps as one text, and runs of different sizes share a baseline. Characters drawn in a fallback font now share the baseline of the text around them instead of its top.#114
646d783Thanks @GabeSilvaDev! - A longpdf-textnow breaks between its lines at a page break instead of moving to the next page whole, or being clipped when taller than a page.orphansandwidows(default 2) set the fewest lines kept before and after the break. A text keeps the old behaviour, moving whole, when it hasbreak-inside: avoid, a fixedheightor amax-height, or when it sits inside a table row or a rowpdf-view.
0.2.0
Minor Changes
#110
b2762edThanks @GabeSilvaDev! - Add custom fonts: register TTF, OTF, WOFF or WOFF2 files withprovidePdfFontsand name them infont-family. Text in them is not limited to WinAnsi, and each character falls back along thefont-familylist to the first font that has it. Only the fonts a PDF uses are embedded, as subsets. Documents that name no registered family render exactly as before.#108
318a305Thanks @GabeSilvaDev! - Add thepdfDownloaddirective:<button [pdfDownload]="Invoice" pdfFileName="invoice.pdf">downloads the document when clicked, marks the button busy and ignores clicks while it renders, and reports a failed render through(pdfError)and the app'sErrorHandler.#107
1c4d22aThanks @GabeSilvaDev! - AddpdfResourceto keep a PDF Blob and object URL current as document inputs change. It also exposes loading and error state, revokes replaced URLs, and can debounce bursts of changes.
Patch Changes
#59
17706f7Thanks @arxigen! - Apdf-imagewith element children now rejects the render withngpdf: pdf-image cannot have children (found <pdf-text>), naming the first child, before any image is fetched. The error identifies the element you need to remove.#64
7ac8749Thanks @arxigen! - A;inside quotes or parentheses in astyleattribute no longer ends the declaration, so values such asurl(data:image/png;base64,...)orfont-family: "A;B"are kept whole.#71
f6cbe03Thanks @arxigen! - Text is measured once per render instead of again for every layout pass, so documents with a lot of text lay out faster. The output is unchanged.#55
fc028e9Thanks @arxigen! - An imagesrcwritten as an upper- or mixed-case data URL (DATA:image/png;base64,...) is now decoded instead of being fetched over the network, as URL schemes are case-insensitive.
0.1.3
Patch Changes
#34
3da43bbThanks @GabeSilvaDev! -break-before: pageon an element inside a table row or a rowpdf-view, such as apdf-cell, now starts a new page before that whole row. AbreakBeforeinput on an innerpdf-vieworpdf-textdoes the same. These breaks did nothing before.#37
0326e89Thanks @GabeSilvaDev! - A JPEG with an EXIF orientation from 5 to 8, as portrait phone photos usually have, is now laid out at the size it is displayed at, with width and height swapped, so it keeps its aspect ratio instead of being squeezed into the box of the unrotated picture.#35
ef0e6adThanks @GabeSilvaDev! - Text from thedate,currencyandnumberpipes no longer shows?where the locale uses a thin or narrow no-break space (3:00 PMinen-US,1 234,50 €infr): the Unicode spaces U+2000–U+200A and U+205F are drawn as a normal space, and the no-break ones (U+2007, U+202F) as a no-break space, so3:00 PMstays on one line. A soft hyphen (U+00AD) is no longer drawn as a hyphen in the middle of a word, and a zero-width space (U+200B) is no longer drawn as?; both are removed.#39
a707598Thanks @GabeSilvaDev! - A document nested exactly 64 elements deep now renders when its innermost element holds text or an@if/@forblock. The limit counted that text as one more level and rejected the document withngpdf: nesting deeper than 64, which made the real limit 63 for almost every template.#36
11296e1Thanks @GabeSilvaDev! - A render that fails no longer leaves things behind. If the document component, or a component inside it, throws in its constructor, the services and callbacks of that render's injector are now cleaned up before the error reaches you; before, they stayed alive. Callbacks that a component registered withinject(DestroyRef)before the throw still do not run, because Angular does not hand back the partly created component.downloadanddownloadPdfnow remove their temporary link and free the PDF's memory even when the click throws.#33
cb6a54bThanks @GabeSilvaDev! -padding: auto, andautoon apadding-*side, now throw anngpdf:error instead of becoming 0, since CSS has noautopadding. A negativefont-sizeor padding now throws as well; negative margins still work, as in CSS.gapon apdf-rowinside a table is now named in thengpdf: ignored inside tablesdev-mode warning.
0.1.2
Patch Changes
- #10
b30c004Thanks @GabeSilvaDev! - Rendering a PDF works in an app that hydrated from server-rendered HTML (provideClientHydration()with SSR or prerendering), where it threwTypeError: rNode.getAttribute is not a function.
0.1.1
Patch Changes
- #7
3c457e9Thanks @GabeSilvaDev! -rgb()andrgba()now throw anngpdf: invalid colorerror on hexadecimal, binary or octal channel values such as0x10,0b1and0o7, which CSS does not accept. Documents with deeply nested component hosts now render without a stack overflow. Styles on the host of the document component you render do not affect the PDF: style itspdf-documentorpdf-pageinstead.
0.1.0
Minor Changes
- ba61563: First release. Write a PDF as an Angular component: a document is a normal component whose template uses the
pdf-document,pdf-page,pdf-view,pdf-text,pdf-image,pdf-table,pdf-row,pdf-cellandpdf-page-numberelements. A lazily loaded engine lays it out with Yoga, breaks it into pages and writes it with pdfkit, all in the browser. Importing@ngpdf/coreadds at most 15 KB gzipped to the initial bundle.