From 4e2b7278ed5d4f1147775c9e5e35cdea0b489165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Rapha=C3=ABl=20Matte?= <35611957+jeralm@users.noreply.github.com> Date: Mon, 30 Mar 2020 20:42:10 -0400 Subject: [PATCH] [@types/pdfmake] Overhaul type definitions (cont. from #42787) (#42991) * [@types/pdfmake] Split definitions pdfmake/index.d.ts will only export the node api. pdfmake/interfaces.d.ts will contain all data types pdfmake/build/pdfmake.d.ts will export the browser module api as well as the global namespace object pdfmake/build/vfs_fonts.d.ts will export the vfs for the browser * [@types/pdfmake] Add type references for node and pdfkit * [@types/pdfmake] Remove enums TypeScript enums exist at runtime and should never be used in type declaration files unless they perfectly describe the behaviour of the JS code (which is highly unlikely). pdfMake only expects string literals, so the enums were modeled as unions of string literals. * [@types/pdfmake] Overhaul interfaces All changes were meticulously verified against the official docs, the examples AND the source code. Since the documentation is incomplete, the only real spec I had to work with was the actual implementation, which is less than ideal. * [@types/pdfmake] Update server and browser api files The server api exposes a class as single export object. This means the `export =` syntax is necessary for the type definitions, and the consumers must import the module with an `import PdfPrinter = require('pdfmake')` statement. The browser api expose both a compliant ES6 module and a global 'pdfMake' object, which is why the 'export as namespace' syntax is necessary. * [@types/pdfmake] Update tests The examples provided by the pdfMake playground and repository are all copied in pdfmake-playground-examples-tests.ts and pdfmake-examples-test.ts respectively. The pdfmake-interfaces-tests.ts contains code from the documentation as well as additionnal tests for coverage. The other files test all different flavors of the api. * [@types/pdfmake] Add myself as maintainer * [@types/pdfmake] Layout long union type * [@types/pdfmake] Add PageBreak union type * [@types/pdfmake] Add doc comments * [@types/pdfmake] Fix typo --- types/pdfmake/build/pdfmake.d.ts | 28 + types/pdfmake/build/vfs_fonts.d.ts | 5 + types/pdfmake/index.d.ts | 290 +- types/pdfmake/interfaces.d.ts | 462 +++ types/pdfmake/pdfmake-tests.ts | 1465 ---------- types/pdfmake/test/pdfmake-examples-tests.ts | 2508 +++++++++++++++++ types/pdfmake/test/pdfmake-global-tests.ts | 20 + .../test/pdfmake-import-default-tests.ts | 14 + .../pdfmake/test/pdfmake-interfaces-tests.ts | 238 ++ .../test/pdfmake-module-browser-tests.ts | 46 + .../test/pdfmake-module-server-tests.ts | 33 + .../test/pdfmake-playground-examples-tests.ts | 1438 ++++++++++ types/pdfmake/tsconfig.json | 8 +- 13 files changed, 4809 insertions(+), 1746 deletions(-) create mode 100644 types/pdfmake/build/pdfmake.d.ts create mode 100644 types/pdfmake/build/vfs_fonts.d.ts create mode 100644 types/pdfmake/interfaces.d.ts delete mode 100644 types/pdfmake/pdfmake-tests.ts create mode 100644 types/pdfmake/test/pdfmake-examples-tests.ts create mode 100644 types/pdfmake/test/pdfmake-global-tests.ts create mode 100644 types/pdfmake/test/pdfmake-import-default-tests.ts create mode 100644 types/pdfmake/test/pdfmake-interfaces-tests.ts create mode 100644 types/pdfmake/test/pdfmake-module-browser-tests.ts create mode 100644 types/pdfmake/test/pdfmake-module-server-tests.ts create mode 100644 types/pdfmake/test/pdfmake-playground-examples-tests.ts diff --git a/types/pdfmake/build/pdfmake.d.ts b/types/pdfmake/build/pdfmake.d.ts new file mode 100644 index 0000000000..12e0afda58 --- /dev/null +++ b/types/pdfmake/build/pdfmake.d.ts @@ -0,0 +1,28 @@ +/// +import { BufferOptions, TableLayout, TDocumentDefinitions, TFontDictionary } from '../interfaces'; + +export let vfs: TFontDictionary; +export let fonts: TFontDictionary; +export let tableLayouts: TableLayout; + +export function createPdf( + documentDefinitions: TDocumentDefinitions, + tableLayouts?: TableLayout, + fonts?: TFontDictionary, + vfs?: TFontDictionary, +): TCreatedPdf; + +export interface TCreatedPdf { + download(cb?: () => void, options?: BufferOptions): void; + download(defaultFileName: string, cb?: () => void, options?: BufferOptions): void; + + getBlob(cb: (result: Blob) => void, options?: BufferOptions): void; + getBase64(cb: (result: string) => void, options?: BufferOptions): void; + getBuffer(cb: (result: Buffer) => void, options?: BufferOptions): void; + getDataUrl(cb: (result: string) => void, options?: BufferOptions): void; + getStream(options?: BufferOptions): PDFKit.PDFDocument; // minimal version 0.1.41 + open(options?: BufferOptions, win?: Window | null): void; + print(options?: BufferOptions, win?: Window | null): void; +} + +export as namespace pdfMake; diff --git a/types/pdfmake/build/vfs_fonts.d.ts b/types/pdfmake/build/vfs_fonts.d.ts new file mode 100644 index 0000000000..251b7dd32f --- /dev/null +++ b/types/pdfmake/build/vfs_fonts.d.ts @@ -0,0 +1,5 @@ +import { TFontDictionary } from '../interfaces'; + +export namespace pdfMake { + let vfs: TFontDictionary; +} diff --git a/types/pdfmake/index.d.ts b/types/pdfmake/index.d.ts index 2fcd5957e9..4795e912b3 100644 --- a/types/pdfmake/index.d.ts +++ b/types/pdfmake/index.d.ts @@ -5,289 +5,19 @@ // Enzo Volkmann // Andi Pätzold // Neal Mummau +// Jean-Raphaël Matte // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 3.0 -/// +/// -declare module "pdfmake/build/vfs_fonts" { - let pdfMake: { - vfs: any; - [name: string]: any; - }; +import { BufferOptions, TDocumentDefinitions, TFontDictionary } from './interfaces'; + +// 'export =' syntax forbids any other export. +// tslint:disable-next-line: strict-export-declare-modifiers +declare class PdfPrinter { + constructor(fontDescriptors: TFontDictionary); + createPdfKitDocument(docDefinition: TDocumentDefinitions, options?: BufferOptions): PDFKit.PDFDocument; } -declare module "pdfmake/build/pdfmake" { - let vfs: TFontFamily; - let fonts: { [name: string]: TFontFamilyTypes }; - function createPdf( - documentDefinitions: TDocumentDefinitions, - tableLayouts?: any, - fonts?: any, - vfs?: any - ): TCreatedPdf; - - type PageSize = - "4A0"|"2A0"|"A0"|"A1"|"A2"|"A3"|"A4"|"A5"|"A6"|"A7"|"A8"|"A9"|"A10"| - "B0"|"B1"|"B2"|"B3"|"B4"|"B5"|"B6"|"B7"|"B8"|"B9"|"B10"| - "C0"|"C1"|"C2"|"C3"|"C4"|"C5"|"C6"|"C7"|"C8"|"C9"|"C10"| - "RA1"|"RA2"|"RA3"|"RA4"| - "SRA1"|"SRA2"|"SRA3"|"SRA4"| - "EXECUTIVE"|"FOLIO"|"LEGAL"|"LETTER"|"TABLOID"; - - type PageOrientation = "portrait" | "landscape"; - - type Layout = "noBorders" | "headerLineOnly" | "lightHorizontalLines"; - - type Alignment = "left" | "center" | "right"; - - type Decoration = "underline" | "lineThrough" | "overline"; - - type DecorationStyle = "dashed" | "dotted" | "double" | "wavy"; - - type PageBreak = "before" | "after"; - - let pdfMake: pdfMakeStatic; - - interface TFontFamily { - [fontName: string]: string; - } - - interface TFontFamilyTypes { - normal?: string; - bold?: string; - italics?: string; - bolditalics?: string; - } - - interface TDocumentInformation { - /** the title of the document */ - title?: string; - /** the name of the author */ - author?: string; - /** the subject of the document */ - subject?: string; - /** keywords associated with the document */ - keywords?: string; - } - - type TDocumentHeaderFooterFunction = ( - currentPage: number, - pageCount: number, - pageSize?: { width: number; height: number } - ) => any; - - type Margins = number | [number, number] | [number, number, number, number]; - - interface Style { - /** name of the font */ - font?: any; - /** size of the font in pt */ - fontSize?: number; - fontFeatures?: any; - /** whether to use bold text (default: false) */ - bold?: boolean; - /** whether to use italic text (default: false) */ - italics?: boolean; - /** the alignment of the text */ - alignment?: Alignment; - /** the color of the text (color name e.g., ‘blue’ or hexadecimal color e.g., ‘#ff5500’) */ - color?: string; - /** optional space between columns */ - columnGap?: any; - /** the background color of a table cell */ - fillColor?: string; - /** the background opacity of a table cell */ - fillOpacity?: string; - /** the text decoration to applu (‘underline’ or ‘lineThrough’ or ‘overline’) */ - decoration?: Decoration; - /** (‘dashed’ or ‘dotted’ or ‘double’ or ‘wavy’) */ - decorationStyle?: DecorationStyle; - /** the color of the text decoration, see color */ - decorationColor?: string; - /** the background color of the text */ - background?: any; - /** the line height (default: 1) */ - lineHeight?: number; - characterSpacing?: number; - noWrap?: boolean; - /** the color of the bullets in a buletted list */ - markerColor?: string; - leadingIndent?: any; - [additionalProperty: string]: any; - } - - type TableRowFunction = (row: number) => number; - - interface TableLayoutFunctions { - hLineWidth?: (i: number, node: any) => number; - vLineWidth?: (i: number, node: any) => number; - hLineColor?: (i: number, node: any) => string; - vLineColor?: (i: number, node: any) => string; - fillColor?: (i: number, node: any) => string; - paddingLeft?: (i: number, node: any) => number; - paddingRight?: (i: number, node: any) => number; - paddingTop?: (i: number, node: any) => number; - paddingBottom?: (i: number, node: any) => number; - } - - interface TableCell { - text: string; - rowSpan?: number; - colSpan?: number; - fillColor?: string; - border?: [boolean, boolean, boolean, boolean]; - } - - interface Table { - body: Content[][] | TableCell[][]; - dontBreakRows?: boolean; - headerRows?: number; - heights?: Array | TableRowFunction; - layout?: string | TableLayoutFunctions; - widths?: Array; - } - - interface Content { - layout?: Layout; - style?: string | string[]; - margin?: Margins; - text?: string | string[] | Content[]; - columns?: Content[]; - stack?: Content[]; - image?: string; - svg?: string; - width?: string | number; - height?: string | number; - fit?: [number, number]; - pageBreak?: PageBreak; - alignment?: Alignment; - table?: Table; - /** to treat a paragraph as a bulleted list, set an array of items under the ul key */ - ul?: Content[]; - /** for numbered lists set the ol key */ - ol?: Content[]; - qr?: string; - toc?: TableOfContent; - tocItem?: boolean | string | string[]; - [additionalProperty: string]: any; - } - - interface TableOfContent { - id?: string; - title: Content; - } - - interface TDocumentDefinitions { - background?: string | ((currentPage: number, pageSize: PageSize) => string | Content | null); - compress?: boolean; - content: string | Content | Array; - defaultStyle?: Style; - footer?: TDocumentHeaderFooterFunction | Content | string; - header?: TDocumentHeaderFooterFunction | Content | string; - images?: { [key: string]: string }; - info?: TDocumentInformation; - pageBreakBefore?: ( - currentNode?: CurrentNode, - followingNodesOnPage?: any, - nodesOnNextPage?: any, - previousNodesOnPage?: any - ) => boolean; - pageMargins?: Margins; - pageOrientation?: PageOrientation; - pageSize?: PageSize | { width: number; height: number }; - styles?: Style; - watermark?: Watermark; - } - - interface CurrentNode { - id: string; - headlineLevel: string; - text: string | string[] | Content[]; - ul: Content[]; - ol: Content[]; - table: Table; - image: string; - qr: string; - canvas: string; - columns: Content[]; - style: string | string[]; - pageOrientation: PageOrientation; - pageNumbers: number[]; - pages: number; - stack: boolean; - startPosition: { - pageNumber: number; - pageOrientation: PageOrientation; - left: number; - right: number; - verticalRatio: number; - horizontalRatio: number; - }; - } - - interface Pagesize { - height: number; - width: number; - orientation: PageOrientation; - } - - interface Page { - items: any[]; - pageSize: Pagesize; - } - - interface BufferOptions { - autoPrint?: boolean; - } - - type CreatedPdfDownloadParams = ( - defaultFileName?: string, - cb?: () => void, - options?: BufferOptions - ) => void; - - type CreatedPdfOpenPrintParams = ( - options?: BufferOptions, - win?: Window | null - ) => void; - - type CreatedPdfBufferParams = ( - cb: (result: any, pages: Page[]) => void, - options?: BufferOptions - ) => void; - - interface TCreatedPdf { - download: CreatedPdfDownloadParams; - getBlob: CreatedPdfBufferParams; - getBase64: CreatedPdfBufferParams; - getBuffer: CreatedPdfBufferParams; - getDataUrl: CreatedPdfBufferParams; - getStream: CreatedPdfBufferParams; // minimal version 0.1.41 - open: CreatedPdfOpenPrintParams; - print: CreatedPdfOpenPrintParams; - } - - interface pdfMakeStatic { - vfs: TFontFamily; - fonts: { [name: string]: TFontFamilyTypes }; - createPdf(documentDefinitions: TDocumentDefinitions): TCreatedPdf; - } - - interface Watermark { - /** watermark text */ - text?: string; - /** color of text */ - color?: string; - /** opacity of text */ - opacity?: number; - /** bold style of text */ - bold?: boolean; - /** italics style of text */ - italics?: true; - /** own font size of text (ideal size is calculated automatically) (minimal version: 0.1.60) */ - fontSize?: number; - /** angle of text rotation (minimal version: 0.1.60) */ - angle?: number; - } -} +export = PdfPrinter; diff --git a/types/pdfmake/interfaces.d.ts b/types/pdfmake/interfaces.d.ts new file mode 100644 index 0000000000..4f3a52d256 --- /dev/null +++ b/types/pdfmake/interfaces.d.ts @@ -0,0 +1,462 @@ +/// +/// + +export type PageSize = PredefinedPageSize | CustomPageSize; + +export interface CustomPageSize { + width: number; + height: number | 'auto'; +} + +export type PredefinedPageSize = + | '4A0' | '2A0' + | 'A0' | 'A1' | 'A2' | 'A3' | 'A4' | 'A5' | 'A6' | 'A7' | 'A8' | 'A9' | 'A10' + | 'B0' | 'B1' | 'B2' | 'B3' | 'B4' | 'B5' | 'B6' | 'B7' | 'B8' | 'B9' | 'B10' + | 'C0' | 'C1' | 'C2' | 'C3' | 'C4' | 'C5' | 'C6' | 'C7' | 'C8' | 'C9' | 'C10' + | 'RA1' | 'RA2' | 'RA3' | 'RA4' + | 'SRA1' | 'SRA2' | 'SRA3' | 'SRA4' + | 'EXECUTIVE' | 'FOLIO' | 'LEGAL' | 'LETTER' | 'TABLOID'; + +export type PageOrientation = 'portrait' | 'landscape'; + +export type PageBreak = 'before' | 'after'; + +export type Size = + | number // absolute + | 'auto' + | '*' + | string; // percentage + +export interface TFontDictionary { + [fontName: string]: TFontFamilyTypes; +} + +export interface TFontFamilyTypes { + normal?: string; + bold?: string; + italics?: string; + bolditalics?: string; +} + +export interface TDocumentInformation { + /** the title of the document */ + title?: string; + /** the name of the author */ + author?: string; + /** the subject of the document */ + subject?: string; + /** keywords associated with the document */ + keywords?: string; + creator?: string; + producer?: string; + creationDate?: Date; + modDate?: Date; + trapped?: string; +} + +export type DynamicContent = ( + currentPage: number, + pageCount: number, + pageSize: ContextPageSize, +) => Content | null | undefined; + +export type DynamicBackground = (currentPage: number, pageSize: ContextPageSize) => Content | null | undefined; + +export type Margins = number | [number, number] | [number, number, number, number]; + +export type Decoration = 'underline' | 'lineThrough' | 'overline'; +export type DecorationStyle = 'dashed' | 'dotted' | 'double' | 'wavy'; + +export type Alignment = 'left' | 'right' | 'justify' | 'center'; + +export type DynamicRowSize = (row: number) => number | 'auto'; + +export interface CustomTableLayout { + hLineWidth?: DynamicLayout; + vLineWidth?: DynamicLayout; + hLineColor?: string | DynamicLayout; + vLineColor?: string | DynamicLayout; + hLineStyle?: DynamicLayout; + vLineStyle?: DynamicLayout; + fillColor?: string | DynamicLayout; + paddingLeft?: number | DynamicLayout; + paddingRight?: number | DynamicLayout; + paddingTop?: DynamicLayout; + paddingBottom?: DynamicLayout; + fillOpacity?: number | DynamicLayout; + defaultBorder?: boolean; +} + +export type DynamicLayout = (rowIndex: number, node: ContentTable, columnIndex: number) => T | null | undefined; + +export interface LineStyle { + dash?: { + length: number; + space?: number; + }; +} + +export type TableCell = + | {} // Used when another cell spans over this cell + | (Content & { + rowSpan?: number; + colSpan?: number; + border?: [boolean, boolean, boolean, boolean]; + borderColor?: [string, string, string, string]; + fillOpacity?: number; + }); + +export interface Table { + body: TableCell[][]; + widths?: Size[]; + heights?: number | number[] | DynamicRowSize; + headerRows?: number; + dontBreakRows?: boolean; + keepWithHeaderRows?: number; + layout?: TableLayout; +} + +export type PredefinedTableLayout = 'noBorders' | 'headerLineOnly' | 'lightHorizontalLines'; +export type TableLayout = PredefinedTableLayout | CustomTableLayout; + +export interface Style { + /** name of the font */ + font?: string; + /** size of the font in pt */ + fontSize?: number; + fontFeatures?: PDFKit.Mixins.OpenTypeFeatures[]; + /** the line height (default: 1) */ + lineHeight?: number; + /** whether to use bold text (default: false) */ + bold?: boolean; + /** whether to use italic text (default: false) */ + italics?: boolean; + /** the alignment of the text */ + alignment?: Alignment; + /** the color of the text (color name e.g., ‘blue’ or hexadecimal color e.g., ‘#ff5500’) */ + color?: string; + /** the background color of the text */ + background?: string; + /** the color of the bullets in a buletted list */ + markerColor?: string; + /** the text decoration to applu (‘underline’ or ‘lineThrough’ or ‘overline’) */ + decoration?: Decoration; + /** (‘dashed’ or ‘dotted’ or ‘double’ or ‘wavy’) */ + decorationStyle?: DecorationStyle; + /** the color of the text decoration, see color */ + decorationColor?: string; + margin?: Margins; + preserveLeadingSpaces?: boolean; + opacity?: number; + characterSpacing?: number; + leadingIndent?: number; + // Table-cell properties: + noWrap?: boolean; + /** the background color of a table cell */ + fillColor?: string; + /** the background opacity of a table cell */ + fillOpacity?: number; + /** optional space between columns */ + columnGap?: Size; + // These properties appear in the documentation but don't do anything: + // tableCellPadding?: unknown; + // cellBorder?: unknown; + // headerCellBorder?: unknown; + // oddRowCellBorder?: unknown; + // evenRowCellBorder?: unknown; + // tableBorder?: unknown; +} + +export type Content = + | string + | ArrayOfContent + | ContentText + | ContentColumns + | ContentStack + | ContentUnorderedList + | ContentOrderedList + | ContentTable + | ContentAnchor + | ContentPageReference + | ContentTextReference + | ContentToc + | ContentTocItem + | ContentImage + | ContentSvg + | ContentQr + | ContentCanvas; + +// not exported, only used to prevent Content from circularly referencing itself +interface ArrayOfContent extends Array {} + +export interface ContentText extends ContentLink, ContentBase { + text: Content; +} + +export interface ContentColumns extends ContentBase { + columns: Column[]; +} + +export interface ContentStack extends ContentBase { + stack: Content[]; +} + +/** for numbered lists set the ol key */ +export interface ContentOrderedList extends ContentBase { + ol: OrderedListElement[]; + type?: OrderedListType; + markerColor?: string; + separator?: string | [string, string]; + reversed?: boolean; + start?: number; +} + +/** to treat a paragraph as a bulleted list, set an array of items under the ul key */ +export interface ContentUnorderedList extends ContentBase { + ul: UnorderedListElement[]; + type?: UnorderedListType; + markerColor?: string; +} + +export interface ContentCanvas extends ContentBase { + canvas: CanvasElement[]; +} + +export interface ContentSvg extends ContentBase { + svg: string; + width?: number; + height?: number; + fit?: [number, number]; +} + +export interface ContentImage extends ContentLink, ContentBase { + image: string; + width?: number; + height?: number; + fit?: [number, number]; +} + +export interface ContentTable extends ContentBase { + table: Table; + layout?: TableLayout; +} + +export interface ContentAnchor extends ContentBase { + text: string | ContentAnchor; + id: string; +} + +export interface ContentTocItem extends ContentBase { + text: string | ContentTocItem; + tocItem: boolean | string | string[]; + tocStyle?: string | string[] | Style; + tocNumberStyle?: string | string[] | Style; + tocMargin?: Margins; +} + +export interface ContentPageReference extends ContentBase { + pageReference: string; +} + +export interface ContentTextReference extends ContentBase { + textReference: string; +} + +export interface ContentToc extends ContentBase { + toc: TableOfContent; +} + +export interface ContentQr extends ContentBase { + qr: string; + foreground?: string; + fit?: number; + version?: number; + eccLevel?: 'L' | 'M' | 'Q' | 'H'; + mode?: 'numeric' | 'alphanumeric' | 'octet'; + mask?: number; +} + +export interface ContentBase extends Style { + style?: string | string[] | Style; + absolutePosition?: { x: number; y: number }; + relativePosition?: { x: number; y: number }; + pageBreak?: PageBreak; + pageOrientation?: PageOrientation; + headlineLevel?: number; +} + +export interface ContentLink { + link?: string; + linkToPage?: number; + linkToDestination?: string; +} + +export interface TableOfContent { + title?: Content; + textMargin?: Margins; + textStyle?: string | string[] | Style; + numberStyle?: string | string[] | Style; + id?: string; +} + +export type Column = Content & { + width?: Size; +}; + +export type OrderedListType = 'lower-alpha' | 'upper-alpha' | 'lower-roman' | 'upper-roman' | 'none'; +export type OrderedListElement = Content & { + counter?: number; + listType?: OrderedListType; +}; + +export type UnorderedListType = 'square' | 'circle' | 'none'; +export type UnorderedListElement = Content & { + listType?: UnorderedListType; +}; + +export type CanvasElement = CanvasRect | CanvasPolyline | CanvasLine | CanvasEllipse; + +export interface CanvasRect extends CanvasLineElement, CanvasFilledElement { + type: 'rect'; + x: number; + y: number; + w: number; + h: number; + r?: number; +} + +export interface CanvasPolyline extends CanvasLineElement, CanvasFilledElement { + type: 'polyline'; + points: Array<{ x: number; y: number }>; + closePath?: boolean; + lineCap?: 'round' | 'square'; +} + +export interface CanvasLine extends CanvasLineElement { + type: 'line'; + x1: number; + y1: number; + x2: number; + y2: number; + lineCap?: 'round' | 'square'; +} + +export interface CanvasEllipse extends CanvasLineElement, CanvasFilledElement { + type: 'ellipse'; + x: number; + y: number; + r1: number; + r2?: number; +} + +export interface CanvasFilledElement { + color?: string; + fillOpacity?: number; + linearGradient?: string[]; +} + +export interface CanvasLineElement { + lineWidth?: number; + lineColor?: string; + dash?: { + length: number; + space?: number; + }; +} + +export interface StyleDictionary { + [name: string]: Style; +} + +export type PDFVersion = '1.3' | '1.4' | '1.5' | '1.6' | '1.7' | '1.7ext3'; + +export interface Watermark { + /** watermark text */ + text: string; + /** opacity of text */ + opacity?: number; + /** angle of text rotation (minimal version: 0.1.60) */ + angle?: number; + font?: string; + /** own font size of text (ideal size is calculated automatically) (minimal version: 0.1.60) */ + fontSize?: number; + /** color of text */ + color?: string; + /** bold style of text */ + bold?: boolean; + /** italics style of text */ + italics?: boolean; +} + +export interface TDocumentDefinitions { + content: Content; + background?: DynamicBackground | Content; + compress?: boolean; + defaultStyle?: Style; + footer?: DynamicContent | Content; + header?: DynamicContent | Content; + images?: { [key: string]: string }; + info?: TDocumentInformation; + pageBreakBefore?: ( + currentNode: Node, + followingNodesOnPage: Node[], + nodesOnNextPage: Node[], + previousNodesOnPage: Node[], + ) => boolean; + pageMargins?: Margins; + pageOrientation?: PageOrientation; + pageSize?: PageSize; + styles?: StyleDictionary; + userPassword?: string; + ownerPassword?: string; + permissions?: PDFKit.DocumentPermissions; + version?: PDFVersion; + watermark?: string | Watermark; +} + +export interface Node { + text?: Content; + ul?: UnorderedListElement[]; + ol?: OrderedListElement[]; + table?: Table; + image?: string; + qr?: string; + canvas?: CanvasElement; + svg?: string; + columns?: Column[]; + id?: string; + headlineLevel?: number; + style?: string | string[] | Style; + pageBreak?: PageBreak; + pageOrientation?: PageOrientation; + pageNumbers: number[]; + pages: number; + stack: boolean; + startPosition: { + pageNumber: number; + pageOrientation: PageOrientation; + pageInnerHeight: number; + pageInnerWidth: number; + left: number; + top: number; + verticalRatio: number; + horizontalRatio: number; + }; +} + +export interface ContextPageSize { + height: number; + width: number; + orientation: PageOrientation; +} + +export interface BufferOptions { + fontLayoutCache?: boolean; + bufferPages?: boolean; + tableLayouts?: TableLayout; + autoPrint?: boolean; + progressCallback?: (progress: number) => void; +} + +// disable automatic exporting +export {}; diff --git a/types/pdfmake/pdfmake-tests.ts b/types/pdfmake/pdfmake-tests.ts deleted file mode 100644 index 310030b6e0..0000000000 --- a/types/pdfmake/pdfmake-tests.ts +++ /dev/null @@ -1,1465 +0,0 @@ -import * as pdfMake from 'pdfmake/build/pdfmake'; -import * as pdfFonts from 'pdfmake/build/vfs_fonts'; - -const definitions: pdfMake.TDocumentDefinitions[] = [ - { - content: [ - 'First paragraph', - 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines' - ] - }, - { - content: [ - { - text: 'This is a header, using header style', - style: 'header' - }, - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. \n\n', - { - text: 'Subheader 1 - using subheader style', - style: 'subheader' - }, - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. ', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. ', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. \n\n', - { - text: 'Subheader 2 - using subheader style', - style: 'subheader' - }, - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. ', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. \n\n', - { - text: 'It is possible to apply multiple styles, ', - style: ['quote', 'small'] - } - ], - styles: { - header: { - fontSize: 18, - bold: true - }, - subheader: { - fontSize: 15, - bold: true - }, - quote: { - italics: true - }, - small: { - fontSize: 8 - } - } - }, - { - content: [ - { - text: 'This is a header (whole paragraph uses the same header style)\n\n', - style: 'header' - }, - { - text: [ - 'It is however possible to provide an array of texts ', - 'to the paragraph (instead of a single string) and have ', - { text: 'a better ', fontSize: 15, bold: true }, - 'control over it. \nEach inline can be ', - { text: 'styled ', fontSize: 20 }, - { text: 'independently ', italics: true, fontSize: 40 }, - 'then.\n\n' - ] - }, - { text: 'Mixing named styles and style-overrides', style: 'header' }, - { - style: 'bigger', - italics: false, - text: [ - 'We can also mix named-styles and style-overrides at both paragraph and inline level. ', - 'For example, this paragraph uses the "bigger" style, which changes fontSize to 15 and sets italics to true. ', - 'Texts are not italics though. It\'s because we\'ve overriden italics back to false at ', - 'the paragraph level. \n\n', - 'We can also change the style of a single inline. Let\'s use a named style called header: ', - { text: 'like here.\n', style: 'header' }, - 'It got bigger and bold.\n\n', - 'OK, now we\'re going to mix named styles and style-overrides at the inline level. ', - 'We\'ll use header style (it makes texts bigger and bold), but we\'ll override ', - 'bold back to false: ', - { text: 'wow! it works!', style: 'header', bold: false }, - '\n\nMake sure to take a look into the sources to understand what\'s going on here.' - ] - } - ], - styles: { - header: { - fontSize: 18, - bold: true - }, - bigger: { - fontSize: 15, - italics: true - } - } - }, - { - content: [ - { - text: 'This paragraph uses header style and extends the alignment property', - style: 'header', - alignment: 'center' - }, - { - text: [ - 'This paragraph uses header style and overrides bold value setting it back to false.\n', - 'Header style in this example sets alignment to justify, so this paragraph should be rendered \n', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret ' - ], - style: 'header', - bold: false - } - ], - styles: { - header: { - fontSize: 18, - bold: true, - alignment: 'justify' - } - } - }, - { - content: [ - 'By default paragraphs are stacked one on top of (or actually - below) another. ', - 'It\'s possible however to split any paragraph (or even the whole document) into columns.\n\n', - 'Here we go with 2 star-sized columns, with justified text and gap set to 20:\n\n', - { - alignment: 'justify', - columns: [ - { - text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' - }, - { - text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' - } - ] - }, - '\nStar-sized columns have always equal widths, so if we define 3 of those, ', - 'it\'ll look like this (make sure to scroll to the next page, as we have a couple of more examples):\n\n', - { - columns: [ - { - text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' - }, - { - text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' - }, - { - text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' - } - ] - }, - '\nYou can also specify accurate widths for some (or all columns)', - { - columns: [ - { - width: 90, - text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' - }, - { - width: '*', - text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' - }, - { - width: '*', - text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' - }, - { - width: 90, - text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' - } - ] - }, - '\nWe also support auto columns. They set their widths based on the content:\n\n', - { - columns: [ - { - width: 'auto', - text: 'auto column' - }, - { - width: '*', - text: 'This is a star-sized column. It should get the remaining' - + ' space divided by the number of all star-sized columns.' - }, - { - width: 50, - text: 'this one has specific width set to 50' - }, - { - width: 'auto', - text: 'another auto column' - }, - { - width: '*', - text: 'This is a star-sized column. It should get the remaining space ' - + 'divided by the number of all star-sized columns.' - }, - ] - }, - '\nIf all auto columns fit within available width, the table does not occupy whole space:\n\n', - { - columns: [ - { - width: 'auto', - text: 'val1' - }, - { - width: 'auto', - text: 'val2' - }, - { - width: 'auto', - text: 'value3' - }, - { - width: 'auto', - text: 'value 4' - }, - ] - }, - '\nAnother cool feature of pdfmake is the ability to have nested elements.', - { - columns: [ - { - width: 100, - fontSize: 9, - text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. ' - }, - [ - 'As you can see in the document definition - this column is not defined with ', - 'an object, but an array, which means it\'s treated as an array of paragraphs rendered one below another.', - 'Just like on the top-level of the document. Let\'s try to divide the remaing space into 3 star-sized columns:\n\n', - { - columns: [ - { text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, - { text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, - { text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' }, - ] - } - ] - ] - }, - '\n\nOh, don\'t forget, we can use everything from styling examples (named styles, custom overrides) here as well.\n\n', - 'For instance - our next paragraph will use the \'bigger\' style (with fontSize set to 15 and italics - true).', - ' We\'ll split it into three columns and make sure they inherit the style:\n\n', - { - style: 'bigger', - columns: [ - 'First column (BTW - it\'s defined as a single string value. pdfmake will turn it into appropriate structure ', - 'automatically and make sure it inherits the styles', - { - fontSize: 20, - text: 'In this column, we\'ve overriden fontSize to 20. It means the content should have italics=true' - + ' (inherited from the style) and be a little bit bigger' - }, - { - style: 'header', - text: 'Last column does not override any styling properties, but applies a new style (header) to itself.' - + ' Eventually - texts here have italics=true (from bigger) and derive fontSize from the style.' - + ' OK, but which one? Both styles define it. As we already know from our styling examples, multiple' - + ' styles can be applied to the element and their order is important. Because \'header\' style has been' - + ' set after \'bigger\' its fontSize takes precedence over the fontSize from \'bigger\'. This is how it works. ' - + 'You will find more examples in the unit tests.' - } - ] - }, - '\n\nWow, you\'ve read the whole document! Congratulations :D' - ], - styles: { - header: { - fontSize: 18, - bold: true - }, - bigger: { - fontSize: 15, - italics: true - } - }, - defaultStyle: { - columnGap: 20 - } - }, - { - content: [ - { text: 'Tables', style: 'header' }, - 'Official documentation is in progress, this document is just', - ' a glimpse of what is possible with pdfmake and its layout engine.', - { text: 'A simple table (no headers, no width specified, no spans, no styling)', - style: 'subheader' }, - 'The following table has nothing more than a body array', - { - style: 'tableExample', - table: { - body: [ - ['Column 1', 'Column 2', 'Column 3'], - ['One value goes here', 'Another one here', 'OK?'] - ] - } - }, - { text: 'A simple table with nested elements', style: 'subheader' }, - 'It is of course possible to nest any other type of nodes available in ', - 'pdfmake inside table cells', - { - style: 'tableExample', - table: { - body: [ - ['Column 1', 'Column 2', 'Column 3'], - [ - { - stack: [ - 'Let\'s try an unordered list', - { - ul: [ - 'item 1', - 'item 2' - ] - } - ] - }, - [ - 'or a nested table', - { - table: { - body: [ - ['Col1', 'Col2', 'Col3'], - ['1', '2', '3'], - ['1', '2', '3'] - ] - }, - } - ], - { - text: [ - 'Inlines can be ', - { text: 'styled\n', italics: true }, - { text: 'easily as everywhere else', fontSize: 10 }] - } - ] - ] - } - }, - { text: 'Defining column widths', style: 'subheader' }, - 'Tables support the same width definitions as standard columns:', - { - bold: true, - ul: [ - 'auto', - 'star', - 'fixed value' - ] - }, - { - style: 'tableExample', - table: { - widths: [100, '*', 200, '*'], - body: [ - ['width=100', 'star-sized', 'width=200', 'star-sized'], - ['fixed-width cells have exactly the specified width', - { text: 'nothing interesting here', italics: true, color: 'gray' }, - { text: 'nothing interesting here', italics: true, color: 'gray' }, - { text: 'nothing interesting here', italics: true, color: 'gray' }] - ] - } - }, - { - style: 'tableExample', - table: { - widths: ['*', 'auto'], - body: [ - ['This is a star-sized column. The next column over, an auto-sized column, will wrap to accomodate all the text in this cell.', 'I am auto sized.'], - ] - } - }, - { - style: 'tableExample', - table: { - widths: ['*', 'auto'], - body: [ - ['This is a star-sized column. The next column over, an auto-sized column', - { text: 'I am auto sized.', noWrap: true }], - ] - } - }, - { text: 'Defining row heights', style: 'subheader' }, - { - style: 'tableExample', - table: { - heights: [20, 50, 70], - body: [ - ['row 1 with height 20', 'column B'], - ['row 2 with height 50', 'column B'], - ['row 3 with height 70', 'column B'] - ] - } - }, - 'With same height:', - { - style: 'tableExample', - table: { - heights: 40, - body: [ - ['row 1', 'column B'], - ['row 2', 'column B'], - ['row 3', 'column B'] - ] - } - }, - 'With height from function:', - { - style: 'tableExample', - table: { - heights: (row: number) => { - return (row + 1) * 25; - }, - body: [ - ['row 1', 'column B'], - ['row 2', 'column B'], - ['row 3', 'column B'] - ] - } - }, - { text: 'Column/row spans', pageBreak: 'before', style: 'subheader' }, - 'Each cell-element can set a rowSpan or colSpan', - { - style: 'tableExample', - color: '#444', - table: { - widths: [200, 'auto', 'auto'], - headerRows: 2, - // keepWithHeaderRows: 1, - body: [ - [{ text: 'Header with Colspan = 2', style: 'tableHeader', colSpan: 2, alignment: 'center' }, - {}, { text: 'Header 3', style: 'tableHeader', alignment: 'center' }], - [{ text: 'Header 1', style: 'tableHeader', alignment: 'center' }, - { text: 'Header 2', style: 'tableHeader', alignment: 'center' }, - { text: 'Header 3', style: 'tableHeader', alignment: 'center' }], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - [{ rowSpan: 3, text: 'rowSpan set to 3\nLorem ipsum dolor sit amet' }, - 'Sample value 2', 'Sample value 3'], - ['', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', { colSpan: 2, rowSpan: 2, text: 'Both:\nrowSpan and colSpan\ncan be defined at the same time' }, ''], - ['Sample value 1', '', ''], - ] - } - }, - { text: 'Headers', pageBreak: 'before', style: 'subheader' }, - 'You can declare how many rows should be treated as a header. Headers are', - ' automatically repeated on the following pages', - { text: ['It is also possible to set keepWithHeaderRows to make sure there will be no page-break' - + 'between the header and these rows. Take a look at the document-definition and play with it. ' - + 'If you set it to one, the following table will automatically start on the next page, ' - + 'since there\'s not enough space for the first row to be rendered here'], color: 'gray', italics: true }, - { - style: 'tableExample', - table: { - headerRows: 1, - // dontBreakRows: true, - // keepWithHeaderRows: 1, - body: [ - [{ text: 'Header 1', style: 'tableHeader' }, { text: 'Header 2', style: 'tableHeader' }, - { text: 'Header 3', style: 'tableHeader' }], - [ - 'Lorem ipsum dolor sit amet, ', - 'Lorem ipsum dolor sit amet, ', - 'Lorem ipsum dolor sit amet, ', - ] - ] - } - }, - { text: 'Styling tables', style: 'subheader' }, - 'You can provide a custom styler for the table. Currently it supports:', - { - ul: [ - 'line widths', - 'line colors', - 'cell paddings', - ] - }, - 'with more options coming soon...\n\npdfmake currently has a few predefined styles (see them on the next page)', - { text: 'noBorders:', fontSize: 14, bold: true, pageBreak: 'before', margin: [0, 0, 0, 8] }, - { - style: 'tableExample', - table: { - headerRows: 1, - body: [ - [{ text: 'Header 1', style: 'tableHeader' }, { text: 'Header 2', style: 'tableHeader' }, - { text: 'Header 3', style: 'tableHeader' }], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ] - }, - layout: 'noBorders' - }, - { text: 'headerLineOnly:', fontSize: 14, bold: true, margin: [0, 20, 0, 8] }, - { - style: 'tableExample', - table: { - headerRows: 1, - body: [ - [{ text: 'Header 1', style: 'tableHeader' }, { text: 'Header 2', style: 'tableHeader' }, - { text: 'Header 3', style: 'tableHeader' }], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ] - }, - layout: 'headerLineOnly' - }, - { text: 'lightHorizontalLines:', fontSize: 14, bold: true, margin: [0, 20, 0, 8] }, - { - style: 'tableExample', - table: { - headerRows: 1, - body: [ - [{ text: 'Header 1', style: 'tableHeader' }, { text: 'Header 2', style: 'tableHeader' }, { text: 'Header 3', style: 'tableHeader' }], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ] - }, - layout: 'lightHorizontalLines' - }, - { text: 'but you can provide a custom styler as well', margin: [0, 20, 0, 8] }, - { - style: 'tableExample', - table: { - headerRows: 1, - body: [ - [{ text: 'Header 1', style: 'tableHeader' }, { text: 'Header 2', style: 'tableHeader' }, { text: 'Header 3', style: 'tableHeader' }], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ] - }, - layout: { - hLineWidth: (i: number, node: any) => { - return (i === 0 || i === node.table.body.length) ? 2 : 1; - }, - vLineWidth: (i: number, node: any) => { - return (i === 0 || i === node.table.widths.length) ? 2 : 1; - }, - hLineColor: (i: number, node: any) => { - return (i === 0 || i === node.table.body.length) ? 'black' : 'gray'; - }, - vLineColor: (i: number, node: any) => { - return (i === 0 || i === node.table.widths.length) ? 'black' : 'gray'; - }, - // paddingLeft: function(i, node) { return 4; }, - // paddingRight: function(i, node) { return 4; }, - // paddingTop: function(i, node) { return 2; }, - // paddingBottom: function(i, node) { return 2; }, - // fillColor: (i: number, node: any) => { return null; } - } - }, - { text: 'zebra style', margin: [0, 20, 0, 8] }, - { - style: 'tableExample', - table: { - body: [ - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ['Sample value 1', 'Sample value 2', 'Sample value 3'], - ] - }, - layout: { - fillColor: (i: number, node: any) => { - return (i % 2 === 0) ? '#CCCCCC' : null; - } - } - }, - { text: 'Optional border', fontSize: 14, bold: true, pageBreak: 'before', margin: [0, 0, 0, 8] }, - 'Each cell contains an optional border property: an array of 4 booleans for left border, top border, right border, bottom border.', - { - style: 'tableExample', - table: { - body: [ - [ - { - border: [false, true, false, false], - fillColor: '#eeeeee', - text: 'border:\n[false, true, false, false]' - }, - { - border: [false, false, false, false], - fillColor: '#dddddd', - text: 'border:\n[false, false, false, false]' - }, - { - border: [true, true, true, true], - fillColor: '#eeeeee', - text: 'border:\n[true, true, true, true]' - } - ], - [ - { - rowSpan: 3, - border: [true, true, true, true], - fillColor: '#eeeeff', - text: 'rowSpan: 3\n\nborder:\n[true, true, true, true]' - }, - { - border: undefined, - fillColor: '#eeeeee', - text: 'border:\nundefined' - }, - { - border: [true, false, false, false], - fillColor: '#dddddd', - text: 'border:\n[true, false, false, false]' - } - ], - [ - '', - { - colSpan: 2, - border: [true, true, true, true], - fillColor: '#eeffee', - text: 'colSpan: 2\n\nborder:\n[true, true, true, true]' - }, - '' - ], - [ - '', - { - border: undefined, - fillColor: '#eeeeee', - text: 'border:\nundefined' - }, - { - border: [false, false, true, true], - fillColor: '#dddddd', - text: 'border:\n[false, false, true, true]' - } - ] - ] - }, - layout: { - defaultBorder: false, - } - }, - 'For every cell without a border property, whether it has all borders or not is determined by ', - 'layout.defaultBorder, which is false in the table above and true (by default) in the table below.', - { - style: 'tableExample', - table: { - body: [ - [ - { - border: [false, false, false, false], - fillColor: '#eeeeee', - text: 'border:\n[false, false, false, false]' - }, - { - fillColor: '#dddddd', - text: 'border:\nundefined' - }, - { - fillColor: '#eeeeee', - text: 'border:\nundefined' - }, - ], - [ - { - fillColor: '#dddddd', - text: 'border:\nundefined' - }, - { - fillColor: '#eeeeee', - text: 'border:\nundefined' - }, - { - border: [true, true, false, false], - fillColor: '#dddddd', - text: 'border:\n[true, true, false, false]' - }, - ] - ] - } - }, - 'And some other examples with rowSpan/colSpan...', - { - style: 'tableExample', - table: { - body: [ - [ - '', - 'column 1', - 'column 2', - 'column 3' - ], - [ - 'row 1', - { - rowSpan: 3, - colSpan: 3, - border: [true, true, true, true], - fillColor: '#cccccc', - text: 'rowSpan: 3\ncolSpan: 3\n\nborder:\n[true, true, true, true]' - }, - '', - '' - ], - [ - 'row 2', - '', - '', - '' - ], - [ - 'row 3', - '', - '', - '' - ] - ] - }, - layout: { - defaultBorder: false, - } - }, - { - style: 'tableExample', - table: { - body: [ - [ - { - colSpan: 3, - text: 'colSpan: 3\n\nborder:\n[false, false, false, false]', - fillColor: '#eeeeee', - border: [false, false, false, false] - }, - '', - '' - ], - [ - 'border:\nundefined', - 'border:\nundefined', - 'border:\nundefined' - ] - ] - } - }, - { - style: 'tableExample', - table: { - body: [ - [ - { rowSpan: 3, text: 'rowSpan: 3\n\nborder:\n[false, false, false, false]', fillColor: '#eeeeee', border: [false, false, false, false] }, - 'border:\nundefined', - 'border:\nundefined' - ], - [ - '', - 'border:\nundefined', - 'border:\nundefined' - ], - [ - '', - 'border:\nundefined', - 'border:\nundefined' - ] - ] - } - } - ], - styles: { - header: { - fontSize: 18, - bold: true, - margin: [0, 0, 0, 10] - }, - subheader: { - fontSize: 16, - bold: true, - margin: [0, 10, 0, 5] - }, - tableExample: { - margin: [0, 5, 0, 15] - }, - tableHeader: { - bold: true, - fontSize: 13, - color: 'black' - } - }, - defaultStyle: { - // alignment: 'justify' - } - }, - { - content: [ - { text: 'Unordered list', style: 'header' }, - { - ul: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nUnordered list with longer lines', style: 'header' }, - { - ul: [ - 'item 1', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.', - 'item 3' - ] - }, - { text: '\n\nOrdered list', style: 'header' }, - { - ol: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nOrdered list with longer lines', style: 'header' }, - { - ol: [ - 'item 1', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.', - 'item 3' - ] - }, - { text: '\n\nOrdered list should be descending', style: 'header' }, - { - reversed: true, - ol: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nOrdered list with start value', style: 'header' }, - { - start: 50, - ol: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nOrdered list with own values', style: 'header' }, - { - ol: [ - { text: 'item 1', counter: 10 }, - { text: 'item 2', counter: 20 }, - { text: 'item 3', counter: 30 }, - { text: 'item 4 without own value' } - ] - }, - { text: '\n\nNested lists (ordered)', style: 'header' }, - { - ol: [ - 'item 1', - [ - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.', - { - ol: [ - 'subitem 1', - 'subitem 2', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - { - text: [ - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - ] - }, - - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 4', - 'subitem 5', - ] - } - ], - 'item 3\nsecond line of item3' - ] - }, - { text: '\n\nNested lists (unordered)', style: 'header' }, - { - ol: [ - 'item 1', - 'Lorem ipsum dolor sit amet', - { - ul: [ - 'subitem 1', - 'subitem 2', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - { - text: [ - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - ] - }, - - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 4', - 'subitem 5', - ] - }, - 'item 3\nsecond line of item3', - ] - }, - { text: '\n\nUnordered lists inside columns', style: 'header' }, - { - columns: [ - { - ul: [ - 'item 1', - 'Lorem ipsum dolor sit amet', - ] - }, - { - ul: [ - 'item 1', - 'Lorem ipsum dolor sit amet', - ] - } - ] - }, - { text: '\n\nOrdered lists inside columns', style: 'header' }, - { - columns: [ - { - ol: [ - 'item 1', - 'Lorem ipsum dolor sit amet', - ] - }, - { - ol: [ - 'item 1', - 'Lorem ipsum dolor sit amet', - ] - } - ] - }, - { text: '\n\nNested lists width columns', style: 'header' }, - { - ul: [ - 'item 1', - 'Lorem ipsum dolor sit amet', - { - ol: [ - [ - { - columns: [ - 'column 1', - { - stack: [ - 'column 2', - { - ul: [ - 'item 1', - 'item 2', - { - ul: [ - 'item', - 'item', - 'item', - ] - }, - 'item 4', - ] - } - ] - }, - 'column 3', - 'column 4', - ] - }, - 'subitem 1 in a vertical container', - 'subitem 2 in a vertical container', - ], - 'subitem 2', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - { - text: [ - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - ] - }, - - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 3 - Lorem ipsum dolor sit amet', - 'subitem 4', - 'subitem 5', - ] - }, - 'item 3\nsecond line of item3', - ] - }, - { text: '\n\nUnordered list with square marker type', style: 'header' }, - { - type: 'square', - ul: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nUnordered list with circle marker type', style: 'header' }, - { - type: 'circle', - ul: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nColored unordered list', style: 'header' }, - { - color: 'blue', - ul: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nColored unordered list with own marker color', style: 'header' }, - { - color: 'blue', - markerColor: 'red', - ul: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nColored ordered list', style: 'header' }, - { - color: 'blue', - ol: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nColored ordered list with own marker color', style: 'header' }, - { - color: 'blue', - markerColor: 'red', - ol: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nOrdered list - type: lower-alpha', style: 'header' }, - { - type: 'lower-alpha', - ol: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nOrdered list - type: upper-alpha', style: 'header' }, - { - type: 'upper-alpha', - ol: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - - { text: '\n\nOrdered list - type: upper-roman', style: 'header' }, - { - type: 'upper-roman', - ol: [ - 'item 1', - 'item 2', - 'item 3', - 'item 4', - 'item 5' - ] - }, - { text: '\n\nOrdered list - type: lower-roman', style: 'header' }, - { - type: 'lower-roman', - ol: [ - 'item 1', - 'item 2', - 'item 3', - 'item 4', - 'item 5' - ] - }, - { text: '\n\nOrdered list - type: none', style: 'header' }, - { - type: 'none', - ol: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nUnordered list - type: none', style: 'header' }, - { - type: 'none', - ul: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nOrdered list with own separator', style: 'header' }, - { - separator: ')', - ol: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nOrdered list with own complex separator', style: 'header' }, - { - separator: ['(', ')'], - ol: [ - 'item 1', - 'item 2', - 'item 3' - ] - }, - { text: '\n\nOrdered list with own items type', style: 'header' }, - { - ol: [ - 'item 1', - { text: 'item 2', listType: 'none' }, - { text: 'item 3', listType: 'upper-roman' } - ] - }, - { text: '\n\nUnordered list with own items type', style: 'header' }, - { - ul: [ - 'item 1', - { text: 'item 2', listType: 'none' }, - { text: 'item 3', listType: 'circle' } - ] - }, - ], - styles: { - header: { - bold: true, - fontSize: 15 - } - }, - defaultStyle: { - fontSize: 12 - } - }, - { - content: [ - { - stack: [ - 'This header has both top and bottom margins defined', - { text: 'This is a subheader', style: 'subheader' }, - ], - style: 'header' - }, - { - text: [ - 'Margins have slightly different behavior than other layout properties. ', - 'They are not inherited, unlike anything else. They\'re applied only to those nodes which explicitly ', - 'set margin or style property.\n', - ] - }, - { - text: 'This paragraph (consisting of a single line) directly sets top and bottom margin to 20', - margin: [0, 20], - }, - { - stack: [ - { - text: [ - 'This line begins a stack of paragraphs. The whole stack uses a ', - { text: 'superMargin', italics: true }, - ' style (with margin and fontSize properties).', - ] - }, - { text: ['When you look at the', { text: ' document definition', italics: true }, - ', you will notice that fontSize is inherited by all paragraphs inside the stack.'] }, - 'Margin however is only applied once (to the whole stack).' - ], - style: 'superMargin' - }, - { - stack: [ - 'I\'m not sure yet if this is the desired behavior. I find it a better approach however.', - ' One thing to be considered in the future is an explicit layout property called inheritMargin which could opt-in the inheritance.\n\n', - { - fontSize: 15, - text: [ - 'Currently margins for ', - /* the following margin definition doesn't change anything */ - { text: 'inlines', margin: 20 }, - ' are ignored\n\n' - ], - }, - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n', - 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.\n', - ], - margin: [0, 20, 0, 0], - alignment: 'justify' - } - ], - styles: { - header: { - fontSize: 18, - bold: true, - alignment: 'right', - margin: [0, 190, 0, 80] - }, - subheader: { - fontSize: 14 - }, - superMargin: { - margin: [20, 0, 40, 0], - fontSize: 15 - } - } - }, - { - content: [ - 'pdfmake (since it\'s based on pdfkit) supports JPEG and PNG format', - 'If no width/height/fit is provided, image original size will be used', - { - image: 'sampleImage.jpg', - }, - 'If you specify width, image will scale proportionally', - { - image: 'sampleImage.jpg', - width: 150 - }, - 'If you specify both width and height - image will be stretched', - { - image: 'sampleImage.jpg', - width: 150, - height: 150, - }, - 'You can also fit the image inside a rectangle', - { - image: 'sampleImage.jpg', - fit: [100, 100], - pageBreak: 'after' - }, - // Warning! Make sure to copy this definition and paste it to an - // external text editor, as the online AceEditor has some troubles - // with long dataUrl lines and the following image values look like - // they're empty. - 'Images can be also provided in dataURL format...', - { - image: 'data:image/gif;base64,...', - width: 200 - }, - 'or be declared in an "images" dictionary and referenced by name', - { - image: 'building', - width: 200 - }, - ], - images: { - building: 'data:image/gif;base64,...' - } - }, - { - compress: false, - content: ['This document does not use compression'] - }, - // Table of Contents tests - { - content: [ - { - toc: { - title: {text: 'INDEX', style: 'header'} - } - } - ] - }, - { - content: [ - { - toc: { - id: 'mainToc', - title: {text: 'INDEX', style: 'header'} - } - }, - { - text: 'This is a header', - style: 'header', - tocItem: true, - }, - { - text: 'This is a header', - style: 'header', - tocItem: 'mainToc' // if is used id in toc - }, - { - text: 'This is a header', - style: 'header', - tocItem: ['mainToc', 'subToc'] // for multiple tocs - } - ] - }, - // Watermark tests - { - content: "Watermark content", - watermark: { - text: "Test Environment", - color: "red", - opacity: 0.3, - bold: true, - italics: true, - fontSize: 20, - angle: 70 - } - } -]; - -const downloadPdf = () => { - const pdf = pdfMake; - pdf.vfs = pdfFonts.pdfMake.vfs; - - for (const def of definitions) { - pdfMake.createPdf(def).download(); - } -}; - -const openPdf = () => { - const pdf = pdfMake; - pdf.vfs = pdfFonts.pdfMake.vfs; - - for (const def of definitions) { - pdfMake.createPdf(def).open(); - } -}; - -const openPdfInSameWindow = () => { - const pdf = pdfMake; - pdf.vfs = pdfFonts.pdfMake.vfs; - - for (const def of definitions) { - pdfMake.createPdf(def).open({}, window); - } -}; - -const printPdf = () => { - const pdf = pdfMake; - pdf.vfs = pdfFonts.pdfMake.vfs; - - for (const def of definitions) { - pdfMake.createPdf(def).print(); - } -}; - -const printPdfInSameWindow = () => { - const pdf = pdfMake; - pdf.vfs = pdfFonts.pdfMake.vfs; - - for (const def of definitions) { - pdfMake.createPdf(def).print({}, window); - } -}; - -const pdfAsBaseSixtyFourData = () => { - const pdf = pdfMake; - pdf.vfs = pdfFonts.pdfMake.vfs; - - for (const def of definitions) { - const pdfDocGenerator = pdfMake.createPdf(def); - pdfDocGenerator.getBase64((data) => { - alert(data); - }); - } -}; - -const pdfAsBuffer = () => { - const pdf = pdfMake; - pdf.vfs = pdfFonts.pdfMake.vfs; - - for (const def of definitions) { - const pdfDocGenerator = pdfMake.createPdf(def); - pdfDocGenerator.getBuffer((buffer) => { - // ... - }); - } -}; - -const pdfAsBlob = () => { - const pdf = pdfMake; - pdf.vfs = pdfFonts.pdfMake.vfs; - - for (const def of definitions) { - const pdfDocGenerator = pdfMake.createPdf(def); - pdfDocGenerator.getBlob((blob) => { - // ... - }); - } -}; - -const getPdfKitDocumentObject = () => { - const pdf = pdfMake; - pdf.vfs = pdfFonts.pdfMake.vfs; - - for (const def of definitions) { - const pdfDocGenerator = pdfMake.createPdf(def); - pdfDocGenerator.getStream((gs) => { - // ... - }); - } -}; diff --git a/types/pdfmake/test/pdfmake-examples-tests.ts b/types/pdfmake/test/pdfmake-examples-tests.ts new file mode 100644 index 0000000000..e8c5e8df4f --- /dev/null +++ b/types/pdfmake/test/pdfmake-examples-tests.ts @@ -0,0 +1,2508 @@ +import { TDocumentDefinitions } from 'pdfmake/interfaces'; + +const absolute: TDocumentDefinitions = { + content: [ + { + image: 'bee', + width: 50, + height: 50, + absolutePosition: { x: 100, y: 100 }, + }, + { + image: 'bee', + width: 50, + height: 50, + absolutePosition: { x: 150, y: 150 }, + }, + { + image: 'bee', + width: 50, + height: 50, + absolutePosition: { x: 200, y: 200 }, + }, + { + image: 'bee', + width: 50, + height: 50, + absolutePosition: { x: 250, y: 150 }, + }, + { + image: 'bee', + width: 50, + height: 50, + absolutePosition: { x: 300, y: 100 }, + }, + + { + text: 'You can put images at any position', + pageBreak: 'after', + }, + + { + text: 'As', + absolutePosition: { x: 100, y: 100 }, + }, + { + text: 'well', + absolutePosition: { x: 150, y: 150 }, + }, + { + text: 'as', + absolutePosition: { x: 200, y: 200 }, + }, + { + text: 'text', + absolutePosition: { x: 250, y: 150 }, + }, + { + text: '!!!', + absolutePosition: { x: 300, y: 100 }, + pageBreak: 'after', + }, + + { + text: 'And this is a table on top of an image at x:100 y:100', + }, + { + image: 'bee', + width: 100, + height: 100, + absolutePosition: { x: 100, y: 100 }, + }, + { + absolutePosition: { x: 100, y: 100 }, + style: 'tableExample', + table: { + body: [ + ['Column 1', 'Column 2', 'Column 3'], + [ + { + stack: [ + "Let's try an unordered list", + { + ul: ['item 1', 'item 2'], + }, + ], + }, + [ + 'or a nested table', + { + table: { + body: [ + ['Col1', 'Col2', 'Col3'], + ['1', '2', '3'], + ['1', '2', '3'], + ], + }, + }, + ], + { + text: [ + 'Inlines can be ', + { text: 'styled\n', italics: true }, + { + text: 'easily as everywhere else', + fontSize: 10, + }, + ], + }, + ], + ], + }, + }, + ], + images: { + bee: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAACklEQVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg==', + }, + styles: { + header: { + fontSize: 18, + bold: true, + margin: [0, 0, 0, 10], + }, + subheader: { + fontSize: 16, + bold: true, + margin: [0, 10, 0, 5], + }, + tableExample: { + margin: [0, 5, 0, 15], + }, + tableHeader: { + bold: true, + fontSize: 13, + color: 'black', + }, + }, +}; + +const background: TDocumentDefinitions = { + background(page) { + if (page !== 2) { + return [ + 'Background paragraph on page ' + page, + 'Another background paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines', + { + image: 'bee', + width: 200, + }, + ]; + } + }, + content: [ + 'First paragraph', + 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines', + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + 'Another Page', + '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n', + 'Another Page', + ], + + images: { + bee: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAACklEQVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg==', + }, +}; + +const basics: TDocumentDefinitions = { + content: [ + 'First paragraph', + 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines', + ], +}; + +const columnsSimple: TDocumentDefinitions = { + content: [ + 'By default paragraphs are stacked one on top of (or actually - below) another. ', + "It's possible however to split any paragraph (or even the whole document) into columns.\n\n", + 'Here we go with 2 star-sized columns, with justified text and gap set to 20:\n\n', + { + alignment: 'justify', + columns: [ + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + ], + }, + "\nStar-sized columns have always equal widths, so if we define 3 of those, it'll look like this (make sure to scroll to the next page, as we have a couple of more examples):\n\n", + { + columns: [ + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + ], + }, + // tslint:disable-next-line: max-line-length + "\nYou can also specify accurate widths for some (or all columns). Let's make the first column and the last one narrow and let the layout engine divide remaining space equally between other star-columns:\n\n", + { + columns: [ + { + width: 90, + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + width: '*', + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + width: '*', + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + width: 90, + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + ], + }, + '\nWe also support auto columns. They set their widths based on the content:\n\n', + { + columns: [ + { + width: 'auto', + text: 'auto column', + }, + { + width: '*', + text: 'This is a star-sized column. It should get the remaining space divided by the number of all star-sized columns.', + }, + { + width: 50, + text: 'this one has specific width set to 50', + }, + { + width: 'auto', + text: 'another auto column', + }, + { + width: '*', + text: 'This is a star-sized column. It should get the remaining space divided by the number of all star-sized columns.', + }, + ], + }, + '\nIf all auto columns fit within available width, the table does not occupy whole space:\n\n', + { + columns: [ + { + width: 'auto', + text: 'val1', + }, + { + width: 'auto', + text: 'val2', + }, + { + width: 'auto', + text: 'value3', + }, + { + width: 'auto', + text: 'value 4', + }, + ], + }, + // tslint:disable-next-line: max-line-length + '\nAnother cool feature of pdfmake is the ability to have nested elements. Each column is actually quite similar to the whole document, so we can have inner paragraphs and further divisions, like in the following example:\n\n', + { + columns: [ + { + width: 100, + fontSize: 9, + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Conveniunt quieti extremum severitatem disseretur virtute locum virtus declarant. Greges telos detrimenti persius possint eripuit appellat democrito suscipere existimant. Facere usus levitatibus confirmavit, provincia rutilius libris accommodare valetudinis ignota fugienda arbitramur falsarum commodius. Voluptas summis arbitrarer cognitio temperantiamque, fuit posidonium pro assueverit animos inferiorem, affecti honestum ferreum cum tot nemo ius partes dissensio opinor, tuum intellegunt numeris ignorant, odia diligenter licet, sublatum repellere, maior ficta severa quantum mortem. Aut evertitur impediri vivamus.', + }, + [ + // tslint:disable-next-line: max-line-length + "As you can see in the document definition - this column is not defined with an object, but an array, which means it's treated as an array of paragraphs rendered one below another.", + "Just like on the top-level of the document. Let's try to divide the remaing space into 3 star-sized columns:\n\n", + { + columns: [ + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + ], + }, + ], + ], + }, + "\n\nOh, don't forget, we can use everything from styling examples (named styles, custom overrides) here as well.\n\n", + "For instance - our next paragraph will use the 'bigger' style (with fontSize set to 15 and italics - true). We'll split it into three columns and make sure they inherit the style:\n\n", + { + style: 'bigger', + columns: [ + "First column (BTW - it's defined as a single string value. pdfmake will turn it into appropriate structure automatically and make sure it inherits the styles", + { + fontSize: 20, + text: "In this column, we've overriden fontSize to 20. It means the content should have italics=true (inherited from the style) and be a little bit bigger", + }, + { + style: 'header', + // tslint:disable-next-line: max-line-length + text: "Last column does not override any styling properties, but applies a new style (header) to itself. Eventually - texts here have italics=true (from bigger) and derive fontSize from the style. OK, but which one? Both styles define it. As we already know from our styling examples, multiple styles can be applied to the element and their order is important. Because 'header' style has been set after 'bigger' its fontSize takes precedence over the fontSize from 'bigger'. This is how it works. You will find more examples in the unit tests.", + }, + ], + }, + "\n\nWow, you've read the whole document! Congratulations :D", + ], + styles: { + header: { + fontSize: 18, + bold: true, + }, + bigger: { + fontSize: 15, + italics: true, + }, + }, + defaultStyle: { + columnGap: 20, + }, +}; + +const images: TDocumentDefinitions = { + content: [ + "pdfmake (since it's based on pdfkit) supports JPEG and PNG format", + 'If no width/height/fit is provided, image original size will be used', + { + image: 'fonts/sampleImage.jpg', + }, + 'If you specify width, image will scale proportionally', + { + image: 'fonts/sampleImage.jpg', + width: 150, + }, + 'If you specify both width and height - image will be stretched', + { + image: 'fonts/sampleImage.jpg', + width: 150, + height: 150, + }, + 'You can also fit the image inside a rectangle', + { + image: 'fonts/sampleImage.jpg', + fit: [100, 100], + pageBreak: 'after', + }, + 'Images can be also provided in dataURL format\n(the one below was taken from http://www.clipartbest.com/clipart-dT7zx5rT9)', + { + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAACklEQVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg==', + width: 200, + }, + 'or be defined in the "images" dictionary, which can be referenced by name:', + { + image: 'bee', + width: 200, + }, + 'and opacity is supported:', + { + image: 'fonts/sampleImage.jpg', + width: 150, + opacity: 0.5, + }, + ], + images: { + bee: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAACklEQVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg==', + }, +}; + +const links: TDocumentDefinitions = { + content: [ + { + text: [ + 'Link to ', + { + text: 'pdfmake website', + link: 'http://pdfmake.org', + decoration: 'underline', + }, + ' and ', + { + text: 'documentation', + link: 'https://pdfmake.github.io/docs/', + decoration: 'underline', + }, + '.', + ], + }, + { text: 'Go to page 2', linkToPage: 2, decoration: 'underline' }, + { + text: 'Link to header 2', + linkToDestination: 'header2', + decoration: 'underline', + }, + 'Links are also supported with images:', + { + image: 'fonts/sampleImage.jpg', + width: 150, + link: 'http://pdfmake.org', + }, + { + text: 'Header on page 2', + fontSize: 18, + bold: true, + pageBreak: 'before', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sollicitudin. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Suspendisse nisl. Mauris elementum mauris vitae tortor. Phasellus et lorem id felis nonummy placerat. Aliquam erat volutpat. In laoreet, magna id viverra tincidunt, sem odio bibendum justo, vel imperdiet sapien wisi sed libero. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Donec ipsum massa, ullamcorper in, auctor et, scelerisque sed, est. Etiam bibendum elit eget erat. Nullam rhoncus aliquam metus. Proin mattis lacinia justo. Nullam sit amet magna in magna gravida vehicula. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Integer lacinia. Duis sapien nunc, commodo et, interdum suscipit, sollicitudin et, dolor.', + }, + '\n\n', + { text: 'Header 2', id: 'header2', fontSize: 18, bold: true }, + { text: 'Go to page 1', linkToPage: 1, decoration: 'underline' }, + ], +}; + +const lists: TDocumentDefinitions = { + content: [ + { text: 'Unordered list', style: 'header' }, + { + ul: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nUnordered list with longer lines', style: 'header' }, + { + ul: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'item 3', + ], + }, + { text: '\n\nOrdered list', style: 'header' }, + { + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list with longer lines', style: 'header' }, + { + ol: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'item 3', + ], + }, + { text: '\n\nOrdered list should be descending', style: 'header' }, + { + reversed: true, + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list with start value', style: 'header' }, + { + start: 50, + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list with own values', style: 'header' }, + { + ol: [ + { text: 'item 1', counter: 10 }, + { text: 'item 2', counter: 20 }, + { text: 'item 3', counter: 30 }, + { text: 'item 4 without own value' }, + ], + }, + { text: '\n\nNested lists (ordered)', style: 'header' }, + { + ol: [ + 'item 1', + [ + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + ol: [ + 'subitem 1', + 'subitem 2', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + text: [ + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 4', + 'subitem 5', + ], + }, + ], + 'item 3\nsecond line of item3', + ], + }, + { text: '\n\nNested lists (unordered)', style: 'header' }, + { + ol: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + ul: [ + 'subitem 1', + 'subitem 2', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + text: [ + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 4', + 'subitem 5', + ], + }, + 'item 3\nsecond line of item3', + ], + }, + { text: '\n\nUnordered lists inside columns', style: 'header' }, + { + columns: [ + { + ul: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + { + ul: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + ], + }, + { text: '\n\nOrdered lists inside columns', style: 'header' }, + { + columns: [ + { + ol: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + { + ol: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + ], + }, + { text: '\n\nNested lists width columns', style: 'header' }, + { + ul: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + ol: [ + [ + { + columns: [ + 'column 1', + { + stack: [ + 'column 2', + { + ul: [ + 'item 1', + 'item 2', + { + ul: [ + 'item', + 'item', + 'item', + ], + }, + 'item 4', + ], + }, + ], + }, + 'column 3', + 'column 4', + ], + }, + 'subitem 1 in a vertical container', + 'subitem 2 in a vertical container', + ], + 'subitem 2', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + text: [ + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 4', + 'subitem 5', + ], + }, + 'item 3\nsecond line of item3', + ], + }, + { text: '\n\nUnordered list with square marker type', style: 'header' }, + { + type: 'square', + ul: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nUnordered list with circle marker type', style: 'header' }, + { + type: 'circle', + ul: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nColored unordered list', style: 'header' }, + { + color: 'blue', + ul: ['item 1', 'item 2', 'item 3'], + }, + { + text: '\n\nColored unordered list with own marker color', + style: 'header', + }, + { + color: 'blue', + markerColor: 'red', + ul: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nColored ordered list', style: 'header' }, + { + color: 'blue', + ol: ['item 1', 'item 2', 'item 3'], + }, + { + text: '\n\nColored ordered list with own marker color', + style: 'header', + }, + { + color: 'blue', + markerColor: 'red', + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list - type: lower-alpha', style: 'header' }, + { + type: 'lower-alpha', + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list - type: upper-alpha', style: 'header' }, + { + type: 'upper-alpha', + ol: ['item 1', 'item 2', 'item 3'], + }, + + { text: '\n\nOrdered list - type: upper-roman', style: 'header' }, + { + type: 'upper-roman', + ol: ['item 1', 'item 2', 'item 3', 'item 4', 'item 5'], + }, + { text: '\n\nOrdered list - type: lower-roman', style: 'header' }, + { + type: 'lower-roman', + ol: ['item 1', 'item 2', 'item 3', 'item 4', 'item 5'], + }, + { text: '\n\nOrdered list - type: none', style: 'header' }, + { + type: 'none', + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nUnordered list - type: none', style: 'header' }, + { + type: 'none', + ul: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list with own separator', style: 'header' }, + { + separator: ')', + ol: ['item 1', 'item 2', 'item 3'], + }, + { + text: '\n\nOrdered list with own complex separator', + style: 'header', + }, + { + separator: ['(', ')'], + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list with own items type', style: 'header' }, + { + ol: [ + 'item 1', + { text: 'item 2', listType: 'none' }, + { text: 'item 3', listType: 'upper-roman' }, + ], + }, + { text: '\n\nUnordered list with own items type', style: 'header' }, + { + ul: [ + 'item 1', + { text: 'item 2', listType: 'none' }, + { text: 'item 3', listType: 'circle' }, + ], + }, + ], + styles: { + header: { + bold: true, + fontSize: 15, + }, + }, + defaultStyle: { + fontSize: 12, + }, +}; + +const margins: TDocumentDefinitions = { + content: [ + { + stack: [ + 'This header has both top and bottom margins defined', + { text: 'This is a subheader', style: 'subheader' }, + ], + style: 'header', + }, + { + text: [ + "Margins have slightly different behavior than other layout properties. They are not inherited, unlike anything else. They're applied only to those nodes which explicitly ", + 'set margin or style property.\n', + ], + }, + { + text: 'This paragraph (consisting of a single line) directly sets top and bottom margin to 20', + margin: [0, 20], + }, + { + stack: [ + { + text: [ + 'This line begins a stack of paragraphs. The whole stack uses a ', + { text: 'superMargin', italics: true }, + ' style (with margin and fontSize properties).', + ], + }, + { + text: [ + 'When you look at the', + { text: ' document definition', italics: true }, + ', you will notice that fontSize is inherited by all paragraphs inside the stack.', + ], + }, + 'Margin however is only applied once (to the whole stack).', + ], + style: 'superMargin', + }, + { + stack: [ + // tslint:disable-next-line: max-line-length + "I'm not sure yet if this is the desired behavior. I find it a better approach however. One thing to be considered in the future is an explicit layout property called inheritMargin which could opt-in the inheritance.\n\n", + { + fontSize: 15, + text: [ + 'Currently margins for ', + /* the following margin definition doesn't change anything */ + { text: 'inlines', margin: 20 }, + ' are ignored\n\n', + ], + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + ], + margin: [0, 20, 0, 0], + alignment: 'justify', + }, + ], + styles: { + header: { + fontSize: 18, + bold: true, + alignment: 'right', + margin: [0, 190, 0, 80], + }, + subheader: { + fontSize: 14, + }, + superMargin: { + margin: [20, 0, 40, 0], + fontSize: 15, + }, + }, +}; + +const pageReference: TDocumentDefinitions = { + content: [ + { + text: 'This is a page reference example. Page number of text element marked id property will be located in pageReference element. See below.\n\n', + }, + { + table: { + body: [ + [ + { text: 'page #', bold: true }, + { text: 'title', bold: true }, + ], + [ + { pageReference: 'header1', alignment: 'right' }, + 'Header one', + ], + [ + { pageReference: 'subheader1', alignment: 'right' }, + 'Subheader one', + ], + [ + { pageReference: 'subheader2', alignment: 'right' }, + 'Subheader two', + ], + [ + { pageReference: 'subheader3', alignment: 'right' }, + 'Subheader three', + ], + ], + }, + }, + { + text: '\nAnd text can be referenced by textReference:\n', + }, + { + table: { + body: [ + [ + { text: 'page #', bold: true }, + { text: 'title', bold: true }, + ], + [ + { pageReference: 'header1', alignment: 'right' }, + { textReference: 'header1' }, + ], + [ + { pageReference: 'subheader1', alignment: 'right' }, + { textReference: 'subheader1' }, + ], + [ + { pageReference: 'subheader2', alignment: 'right' }, + { textReference: 'subheader2' }, + ], + [ + { pageReference: 'subheader3', alignment: 'right' }, + { textReference: 'subheader3' }, + ], + ], + }, + }, + { + text: '\nAnd all can be in inline texts:\n', + }, + { + text: [ + 'Chapter "', + { textReference: 'header1' }, + '" is on page number ', + { pageReference: 'header1' }, + ], + }, + { + text: [ + 'Chapter "', + { textReference: 'subheader1' }, + '" is on page number ', + { pageReference: 'subheader1' }, + ], + }, + { + text: [ + 'Chapter "', + { textReference: 'subheader2' }, + '" is on page number ', + { pageReference: 'subheader2' }, + ], + }, + { + text: [ + 'Chapter "', + { textReference: 'subheader3' }, + '" is on page number ', + { pageReference: 'subheader3' }, + ], + }, + { + text: 'This is a header, using header style', + style: 'header', + id: 'header1', + pageBreak: 'before', + }, + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam.\n\n', + { + text: 'Subheader 1 - using subheader style', + style: 'subheader', + id: 'subheader1', + pageBreak: 'before', + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n', + { + text: 'Subheader 2 - using subheader style', + style: 'subheader', + id: 'subheader2', + pageBreak: 'before', + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n', + { + // tslint:disable-next-line: max-line-length + text: 'It is possible to apply multiple styles, by passing an array. This paragraph uses two styles: quote and small. When multiple styles are provided, they are evaluated in the specified order which is important in case they define the same properties', + style: ['quote', 'small'], + }, + { + text: [ + { + text: 'Subheader 3 - using inline text', + style: 'subheader', + id: 'subheader3', + tocItem: true, + }, + { + text: '; and this text not be displayed in ToC', + italics: true, + }, + ], + pageBreak: 'before', + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + ], + styles: { + header: { + fontSize: 18, + bold: true, + }, + subheader: { + fontSize: 15, + bold: true, + }, + quote: { + italics: true, + }, + small: { + fontSize: 8, + }, + }, +}; + +const qrCode: TDocumentDefinitions = { + pageMargins: [10, 10, 10, 10], + content: [ + { text: 'Can you see me', style: 'header' }, + { qr: 'Can you see me' }, + '\n', + + { text: 'Colored QR', style: 'header' }, + { + qr: 'Can you see me', + foreground: 'red', + background: 'yellow', + }, + '\n', + + { text: 'http://pdfmake.org', style: 'header' }, + { qr: 'http://pdfmake.org' }, + '\n', + + { text: 'A very long text', style: 'header' }, + { + // tslint:disable-next-line: max-line-length + qr: 'The amount of data that can be stored in the QR code symbol depends on the datatype (mode, or input character set), version (1, …, 40, indicating the overall dimensions of the symbol), and error correction level. The maximum storage capacities occur for 40-L symbols (version 40, error correction level L):', + }, + '\n', + { + text: 'same long text with fit = 150 and alignment = right', + style: 'header', + }, + { + // tslint:disable-next-line: max-line-length + qr: 'The amount of data that can be stored in the QR code symbol depends on the datatype (mode, or input character set), version (1, …, 40, indicating the overall dimensions of the symbol), and error correction level. The maximum storage capacities occur for 40-L symbols (version 40, error correction level L):', + fit: 100, + alignment: 'right', + }, + ], + styles: { + header: { + margin: [0, 0, 0, 8], + }, + }, +}; + +const relative2: TDocumentDefinitions = { + content: [ + { + text: "We sometimes don't know the absolute position of text", + margin: [10, 0, 0, 50], + }, + { + columns: [ + { + width: '50%', + text: 'horizontal position is not known either', + }, + { + width: '50%', + stack: [ + { + stack: [ + { + text: '2016', + fontSize: 8, + relativePosition: { x: 41, y: 127 }, + }, + { + text: '2017', + fontSize: 8, + relativePosition: { x: 66, y: 127 }, + }, + { + text: '2018', + fontSize: 8, + relativePosition: { x: 91, y: 127 }, + }, + { + text: '2019', + fontSize: 8, + relativePosition: { x: 116, y: 127 }, + }, + { + text: '2020', + fontSize: 8, + relativePosition: { x: 141, y: 127 }, + }, + { + text: '5', + fontSize: 8, + relativePosition: { x: 37, y: 15 }, + }, + { + text: '4', + fontSize: 8, + relativePosition: { x: 37, y: 40 }, + }, + { + text: '3', + fontSize: 8, + relativePosition: { x: 37, y: 65 }, + }, + { + text: '2', + fontSize: 8, + relativePosition: { x: 37, y: 90 }, + }, + { + text: '1', + fontSize: 8, + relativePosition: { x: 37, y: 115 }, + }, + ], + }, + { + canvas: [ + { + type: 'line', + x1: 49, + y1: 120, + x2: 150, + y2: 120, + }, + { + type: 'line', + x1: 49.5, + y1: 120, + x2: 49.5, + y2: 125, + }, + { + type: 'line', + x1: 74.5, + y1: 120, + x2: 74.5, + y2: 125, + }, + { + type: 'line', + x1: 99.5, + y1: 120, + x2: 99.5, + y2: 125, + }, + { + type: 'line', + x1: 124.5, + y1: 120, + x2: 124.5, + y2: 125, + }, + { + type: 'line', + x1: 149.5, + y1: 120, + x2: 149.5, + y2: 125, + }, + { + type: 'line', + x1: 49.5, + y1: 19.5, + x2: 49.5, + y2: 119.5, + }, + { + type: 'line', + x1: 44, + y1: 20, + x2: 49, + y2: 20, + }, + { + type: 'line', + x1: 44, + y1: 45, + x2: 49, + y2: 45, + }, + { + type: 'line', + x1: 44, + y1: 70, + x2: 49, + y2: 70, + }, + { + type: 'line', + x1: 44, + y1: 95, + x2: 49, + y2: 95, + }, + { + type: 'line', + x1: 44, + y1: 120, + x2: 49, + y2: 120, + }, + ], + }, + ], + }, + ], + }, + { + text: 'We can position relative with center and right alignment', + margin: [0, 50, 0, 50], + }, + { + table: { + widths: [100, 100, 100], + body: [ + [ + 'Column with a lot of text. Column with a lot of text. Column with a lot of text. Column with a lot of text.', + { + text: "I'm aligned center", + style: { alignment: 'center' }, + relativePosition: { x: 0, y: 25 }, + }, + { + text: "I'm aligned right", + style: { alignment: 'right' }, + relativePosition: { x: 0, y: 25 }, + }, + ], + ], + }, + }, + ], +}; + +const security: TDocumentDefinitions = { + userPassword: '123', + ownerPassword: '123456', + permissions: { + printing: 'highResolution', + modifying: false, + copying: false, + annotating: true, + fillingForms: true, + contentAccessibility: true, + documentAssembly: true, + }, + content: [ + 'Document content with security', + 'For details see to source or documentation.', + ], +}; + +const stylingInlines: TDocumentDefinitions = { + content: [ + { + text: 'This is a header (whole paragraph uses the same header style)\n\n', + style: 'header', + }, + { + text: [ + 'It is however possible to provide an array of texts ', + 'to the paragraph (instead of a single string) and have ', + { text: 'a better ', fontSize: 15, bold: true }, + 'control over it. \nEach inline can be ', + { text: 'styled ', fontSize: 20 }, + { text: 'independently ', italics: true, fontSize: 40 }, + 'then.\n\n', + ], + }, + { text: 'Mixing named styles and style-overrides', style: 'header' }, + { + style: 'bigger', + italics: false, + text: [ + 'We can also mix named-styles and style-overrides at both paragraph and inline level. ', + 'For example, this paragraph uses the "bigger" style, which changes fontSize to 15 and sets italics to true. ', + "Texts are not italics though. It's because we've overriden italics back to false at ", + 'the paragraph level. \n\n', + "We can also change the style of a single inline. Let's use a named style called header: ", + { text: 'like here.\n', style: 'header' }, + 'It got bigger and bold.\n\n', + "OK, now we're going to mix named styles and style-overrides at the inline level. ", + "We'll use header style (it makes texts bigger and bold), but we'll override ", + 'bold back to false: ', + { text: 'wow! it works!', style: 'header', bold: false }, + "\n\nMake sure to take a look into the sources to understand what's going on here.", + ], + }, + ], + styles: { + header: { + fontSize: 18, + bold: true, + }, + bigger: { + fontSize: 15, + italics: true, + }, + }, +}; + +const stylingNamedStylesWithOverrides: TDocumentDefinitions = { + content: [ + { + text: 'This paragraph uses header style and extends the alignment property', + style: 'header', + alignment: 'center', + }, + { + text: [ + 'This paragraph uses header style and overrides bold value setting it back to false.\n', + 'Header style in this example sets alignment to justify, so this paragraph should be rendered \n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + ], + style: 'header', + bold: false, + }, + ], + styles: { + header: { + fontSize: 18, + bold: true, + alignment: 'justify', + }, + }, +}; + +const stylingNamedStyles: TDocumentDefinitions = { + content: [ + { + text: 'This is a header, using header style', + style: 'header', + }, + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam.\n\n', + { + text: 'Subheader 1 - using subheader style', + style: 'subheader', + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n', + { + text: 'Subheader 2 - using subheader style', + style: 'subheader', + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n', + { + // tslint:disable-next-line: max-line-length + text: 'It is possible to apply multiple styles, by passing an array. This paragraph uses two styles: quote and small. When multiple styles are provided, they are evaluated in the specified order which is important in case they define the same properties', + style: ['quote', 'small'], + }, + ], + styles: { + header: { + fontSize: 18, + bold: true, + }, + subheader: { + fontSize: 15, + bold: true, + }, + quote: { + italics: true, + }, + small: { + fontSize: 8, + }, + }, +}; + +const stylingProperties: TDocumentDefinitions = { + content: [ + { + text: 'Paragraphs can also by styled without using named-styles (this one sets fontSize to 25)', + fontSize: 25, + }, + 'Another paragraph, using default style, this time a little bit longer to make sure, this line will be divided into at least two lines\n\n', + { + text: 'This paragraph does not use a named-style and sets fontSize to 8 and italics to true', + fontSize: 8, + italics: true, + }, + '\n\nFor preserving leading spaces use preserveLeadingSpaces property:', + { + text: ' This is a paragraph with preserved leading spaces.', + preserveLeadingSpaces: true, + }, + { text: '{', preserveLeadingSpaces: true }, + { text: ' "sample": {', preserveLeadingSpaces: true }, + { text: ' "json": "nested"', preserveLeadingSpaces: true }, + { text: ' }', preserveLeadingSpaces: true }, + { text: '}', preserveLeadingSpaces: true }, + '\n\nfontFeatures property:', + { text: 'Hello World 1234567890', fontFeatures: ['smcp'] }, + { text: 'Hello World 1234567890', fontFeatures: ['c2sc'] }, + { text: 'Hello World 1234567890', fontFeatures: ['onum'] }, + { text: 'Hello World 1234567890', fontFeatures: ['onum', 'c2sc'] }, + '\n\nText opacity:', + { text: 'Hello World', opacity: 0.8 }, + { text: 'Hello World', opacity: 0.6 }, + { text: 'Hello World', opacity: 0.4 }, + { text: 'Hello World', opacity: 0.2 }, + { text: 'Hello World', opacity: 0.1 }, + ], +}; + +const svgs: TDocumentDefinitions = { + content: [ + 'SVG nodes behave similar to images by supporting width/height or fit', + 'It is however not yet possible to use svg files or to have a library of svgs in the document definition', + '\n', + 'Note that before you can use SVG nodes you must install svg-to-pdfkit as it is not included with pdfmake to keep bundle size down', + { + svg: '', + width: 600, + height: 400, + }, + 'If you specify width, svg will scale proportionally', + { + svg: '', + width: 200, + }, + 'You can also fit the svg inside a rectangle', + { + svg: '', + fit: [100, 100], + }, + ], +}; + +const tables: TDocumentDefinitions = { + content: [ + { text: 'Tables', style: 'header' }, + 'Official documentation is in progress, this document is just a glimpse of what is possible with pdfmake and its layout engine.', + { text: 'A simple table (no headers, no width specified, no spans, no styling)', style: 'subheader' }, + 'The following table has nothing more than a body array', + { + style: 'tableExample', + table: { + body: [ + ['Column 1', 'Column 2', 'Column 3'], + ['One value goes here', 'Another one here', 'OK?'], + ], + }, + }, + { text: 'A simple table with nested elements', style: 'subheader' }, + 'It is of course possible to nest any other type of nodes available in pdfmake inside table cells', + { + style: 'tableExample', + table: { + body: [ + ['Column 1', 'Column 2', 'Column 3'], + [ + { + stack: [ + "Let's try an unordered list", + { + ul: ['item 1', 'item 2'], + }, + ], + }, + [ + 'or a nested table', + { + table: { + body: [ + ['Col1', 'Col2', 'Col3'], + ['1', '2', '3'], + ['1', '2', '3'], + ], + }, + }, + ], + { + text: [ + 'Inlines can be ', + { text: 'styled\n', italics: true }, + { text: 'easily as everywhere else', fontSize: 10 }, + ], + }, + ], + ], + }, + }, + { text: 'Defining column widths', style: 'subheader' }, + 'Tables support the same width definitions as standard columns:', + { + bold: true, + ul: ['auto', 'star', 'fixed value'], + }, + { + style: 'tableExample', + table: { + widths: [100, '*', 200, '*'], + body: [ + ['width=100', 'star-sized', 'width=200', 'star-sized'], + [ + 'fixed-width cells have exactly the specified width', + { text: 'nothing interesting here', italics: true, color: 'gray' }, + { text: 'nothing interesting here', italics: true, color: 'gray' }, + { text: 'nothing interesting here', italics: true, color: 'gray' }, + ], + ], + }, + }, + { + style: 'tableExample', + table: { + widths: ['*', 'auto'], + body: [ + [ + 'This is a star-sized column. The next column over, an auto-sized column, will wrap to accomodate all the text in this cell.', + 'I am auto sized.', + ], + ], + }, + }, + { + style: 'tableExample', + table: { + widths: ['*', 'auto'], + body: [ + [ + 'This is a star-sized column. The next column over, an auto-sized column, will not wrap to accomodate all the text in this cell, because it has been given the noWrap style.', + { text: 'I am auto sized.', noWrap: true }, + ], + ], + }, + }, + { text: 'Defining row heights', style: 'subheader' }, + { + style: 'tableExample', + table: { + heights: [20, 50, 70], + body: [ + ['row 1 with height 20', 'column B'], + ['row 2 with height 50', 'column B'], + ['row 3 with height 70', 'column B'], + ], + }, + }, + 'With same height:', + { + style: 'tableExample', + table: { + heights: 40, + body: [ + ['row 1', 'column B'], + ['row 2', 'column B'], + ['row 3', 'column B'], + ], + }, + }, + 'With height from function:', + { + style: 'tableExample', + table: { + heights(row) { + return (row + 1) * 25; + }, + body: [ + ['row 1', 'column B'], + ['row 2', 'column B'], + ['row 3', 'column B'], + ], + }, + }, + { text: 'Column/row spans', pageBreak: 'before', style: 'subheader' }, + 'Each cell-element can set a rowSpan or colSpan', + { + style: 'tableExample', + color: '#444', + table: { + widths: [200, 'auto', 'auto'], + headerRows: 2, + keepWithHeaderRows: 1, + body: [ + [ + { text: 'Header with Colspan = 2', style: 'tableHeader', colSpan: 2, alignment: 'center' }, + {}, + { text: 'Header 3', style: 'tableHeader', alignment: 'center' }, + ], + [ + { text: 'Header 1', style: 'tableHeader', alignment: 'center' }, + { text: 'Header 2', style: 'tableHeader', alignment: 'center' }, + { text: 'Header 3', style: 'tableHeader', alignment: 'center' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + [ + { + rowSpan: 3, + text: 'rowSpan set to 3\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor', + }, + 'Sample value 2', + 'Sample value 3', + ], + ['', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + [ + 'Sample value 1', + { colSpan: 2, rowSpan: 2, text: 'Both:\nrowSpan and colSpan\ncan be defined at the same time' }, + '', + ], + ['Sample value 1', '', ''], + ], + }, + }, + { text: 'Headers', pageBreak: 'before', style: 'subheader' }, + 'You can declare how many rows should be treated as a header. Headers are automatically repeated on the following pages', + { + text: [ + // tslint:disable-next-line: max-line-length + "It is also possible to set keepWithHeaderRows to make sure there will be no page-break between the header and these rows. Take a look at the document-definition and play with it. If you set it to one, the following table will automatically start on the next page, since there's not enough space for the first row to be rendered here", + ], + color: 'gray', + italics: true, + }, + { + style: 'tableExample', + table: { + headerRows: 1, + dontBreakRows: true, + keepWithHeaderRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + [ + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', + ], + ], + }, + }, + { text: 'Styling tables', style: 'subheader' }, + 'You can provide a custom styler for the table. Currently it supports:', + { + ul: ['line widths', 'line colors', 'cell paddings'], + }, + 'with more options coming soon...\n\npdfmake currently has a few predefined styles (see them on the next page)', + { text: 'noBorders:', fontSize: 14, bold: true, pageBreak: 'before', margin: [0, 0, 0, 8] }, + { + style: 'tableExample', + table: { + headerRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: 'noBorders', + }, + { text: 'headerLineOnly:', fontSize: 14, bold: true, margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + headerRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: 'headerLineOnly', + }, + { text: 'lightHorizontalLines:', fontSize: 14, bold: true, margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + headerRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: 'lightHorizontalLines', + }, + { text: 'but you can provide a custom styler as well', margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + headerRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: { + hLineWidth(i, node) { + return i === 0 || i === node.table.body.length ? 2 : 1; + }, + vLineWidth(i, node) { + return i === 0 || i === node.table.widths!.length ? 2 : 1; + }, + hLineColor(i, node) { + return i === 0 || i === node.table.body.length ? 'black' : 'gray'; + }, + vLineColor(i, node) { + return i === 0 || i === node.table.widths!.length ? 'black' : 'gray'; + }, + hLineStyle(i, node) { + return { dash: { length: 10, space: 4 } }; + }, + vLineStyle(i, node) { + return { dash: { length: 10, space: 4 } }; + }, + paddingLeft(i, node) { + return 4; + }, + paddingRight(i, node) { + return 4; + }, + paddingTop(i, node) { + return 2; + }, + paddingBottom(i, node) { + return 2; + }, + fillColor(rowIndex, node, columnIndex) { + return null; + }, + }, + }, + { text: 'zebra style', margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + body: [ + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: { + fillColor(rowIndex, node, columnIndex) { + return rowIndex % 2 === 0 ? '#CCCCCC' : null; + }, + }, + }, + { text: 'handling fill color opacity...', margin: [0, 20, 0, 8] }, + { text: '... just hardcoding values in the second row', margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + body: [ + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + [ + { text: 'Sample value 1', fillOpacity: 0.15, fillColor: 'blue' }, + { text: 'Sample value 2', fillOpacity: 0.6, fillColor: 'blue' }, + { text: 'Sample value 3', fillOpacity: 0.85, fillColor: 'blue' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + }, + { text: '... using a custom styler and overriding it in the second row', margin: [0, 20, 0, 8] }, + { + style: 'tableOpacityExample', + table: { + body: [ + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + [ + { text: 'Sample value 1', fillOpacity: 0.15 }, + { text: 'Sample value 2', fillOpacity: 0.6 }, + { text: 'Sample value 3', fillOpacity: 0.85 }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + }, + { text: '... with a function (opacity at 0 means fully transparent, i.e no color)', margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + body: [ + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: { + fillColor: 'blue', + fillOpacity(rowIndex, node, columnIndex) { + return rowIndex / 8 + columnIndex / 3; + }, + }, + }, + { text: 'and can be used dash border', margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + headerRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: { + hLineWidth(i, node) { + return i === 0 || i === node.table.body.length ? 2 : 1; + }, + vLineWidth(i, node) { + return i === 0 || i === node.table.widths!.length ? 2 : 1; + }, + hLineColor(i, node) { + return 'black'; + }, + vLineColor(i, node) { + return 'black'; + }, + hLineStyle(i, node) { + if (i === 0 || i === node.table.body.length) { + return null; + } + return { dash: { length: 10, space: 4 } }; + }, + vLineStyle(i, node) { + if (i === 0 || i === node.table.widths!.length) { + return null; + } + return { dash: { length: 4 } }; + }, + paddingLeft(i, node) { + return 4; + }, + paddingRight(i, node) { + return 4; + }, + paddingTop(i, node) { + return 2; + }, + paddingBottom(i, node) { + return 2; + }, + fillColor(i, node) { + return null; + }, + }, + }, + { text: 'Optional border', fontSize: 14, bold: true, pageBreak: 'before', margin: [0, 0, 0, 8] }, + 'Each cell contains an optional border property: an array of 4 booleans for left border, top border, right border, bottom border.', + { + style: 'tableExample', + table: { + body: [ + [ + { + border: [false, true, false, false], + fillColor: '#eeeeee', + text: 'border:\n[false, true, false, false]', + }, + { + border: [false, false, false, false], + fillColor: '#dddddd', + text: 'border:\n[false, false, false, false]', + }, + { + border: [true, true, true, true], + fillColor: '#eeeeee', + text: 'border:\n[true, true, true, true]', + }, + ], + [ + { + rowSpan: 3, + border: [true, true, true, true], + fillColor: '#eeeeff', + text: 'rowSpan: 3\n\nborder:\n[true, true, true, true]', + }, + { + border: undefined, + fillColor: '#eeeeee', + text: 'border:\nundefined', + }, + { + border: [true, false, false, false], + fillColor: '#dddddd', + text: 'border:\n[true, false, false, false]', + }, + ], + [ + '', + { + colSpan: 2, + border: [true, true, true, true], + fillColor: '#eeffee', + text: 'colSpan: 2\n\nborder:\n[true, true, true, true]', + }, + '', + ], + [ + '', + { + border: undefined, + fillColor: '#eeeeee', + text: 'border:\nundefined', + }, + { + border: [false, false, true, true], + fillColor: '#dddddd', + text: 'border:\n[false, false, true, true]', + }, + ], + ], + }, + layout: { + defaultBorder: false, + }, + }, + // tslint:disable-next-line: max-line-length + 'For every cell without a border property, whether it has all borders or not is determined by layout.defaultBorder, which is false in the table above and true (by default) in the table below.', + { + style: 'tableExample', + table: { + body: [ + [ + { + border: [false, false, false, false], + fillColor: '#eeeeee', + text: 'border:\n[false, false, false, false]', + }, + { + fillColor: '#dddddd', + text: 'border:\nundefined', + }, + { + fillColor: '#eeeeee', + text: 'border:\nundefined', + }, + ], + [ + { + fillColor: '#dddddd', + text: 'border:\nundefined', + }, + { + fillColor: '#eeeeee', + text: 'border:\nundefined', + }, + { + border: [true, true, false, false], + fillColor: '#dddddd', + text: 'border:\n[true, true, false, false]', + }, + ], + ], + }, + }, + 'And some other examples with rowSpan/colSpan...', + { + style: 'tableExample', + table: { + body: [ + ['', 'column 1', 'column 2', 'column 3'], + [ + 'row 1', + { + rowSpan: 3, + colSpan: 3, + border: [true, true, true, true], + fillColor: '#cccccc', + text: 'rowSpan: 3\ncolSpan: 3\n\nborder:\n[true, true, true, true]', + }, + '', + '', + ], + ['row 2', '', '', ''], + ['row 3', '', '', ''], + ], + }, + layout: { + defaultBorder: false, + }, + }, + { + style: 'tableExample', + table: { + body: [ + [ + { + colSpan: 3, + text: 'colSpan: 3\n\nborder:\n[false, false, false, false]', + fillColor: '#eeeeee', + border: [false, false, false, false], + }, + '', + '', + ], + ['border:\nundefined', 'border:\nundefined', 'border:\nundefined'], + ], + }, + }, + { + style: 'tableExample', + table: { + body: [ + [ + { + rowSpan: 3, + text: 'rowSpan: 3\n\nborder:\n[false, false, false, false]', + fillColor: '#eeeeee', + border: [false, false, false, false], + }, + 'border:\nundefined', + 'border:\nundefined', + ], + ['', 'border:\nundefined', 'border:\nundefined'], + ['', 'border:\nundefined', 'border:\nundefined'], + ], + }, + }, + { text: 'BorderColor per Cell with Column/row spans', pageBreak: 'before', style: 'subheader' }, + 'Each cell-element can set the borderColor (the cell above or left of the current cell has priority', + { + style: 'tableExample', + color: '#444', + table: { + widths: [200, 'auto', 'auto'], + headerRows: 2, + // keepWithHeaderRows: 1, + body: [ + [ + { + text: 'Header with Colspan = 3', + style: 'tableHeader', + colSpan: 3, + borderColor: ['#ff00ff', '#00ffff', '#ff00ff', '#00ffff'], + alignment: 'center', + }, + {}, + {}, + ], + [ + { + text: 'Header 1', + style: 'tableHeader', + alignment: 'center', + }, + { + text: 'Header 2', + style: 'tableHeader', + alignment: 'center', + }, + { + text: 'Header 3', + style: 'tableHeader', + alignment: 'center', + }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + [ + { + rowSpan: 3, + borderColor: ['#ff00ff', '#00ffff', '#ff00ff', '#00ffff'], + text: 'rowSpan set to 3\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor', + }, + 'Sample value 2', + { + text: 'Sample value 3', + borderColor: ['#ff00ff', '#00ffff', '#ff00ff', '#00ffff'], + }, + ], + ['', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + [ + 'Sample value 1', + { + colSpan: 2, + rowSpan: 2, + borderColor: ['#ff00ff', '#00ffff', '#ff00ff', '#00ffff'], + text: 'Both:\nrowSpan and colSpan\ncan be defined at the same time', + }, + '', + ], + [ + 'Sample value 1', + { + text: 'a', + borderColor: ['#ff00ff', '#00ffff', '#ff00ff', '#00ffff'], + }, + { + text: '', + borderColor: ['#ff00ff', '#00ffff', '#ff00ff', '#00ffff'], + }, + ], + ], + }, + }, + ], + styles: { + header: { + fontSize: 18, + bold: true, + margin: [0, 0, 0, 10], + }, + subheader: { + fontSize: 16, + bold: true, + margin: [0, 10, 0, 5], + }, + tableExample: { + margin: [0, 5, 0, 15], + }, + tableOpacityExample: { + margin: [0, 5, 0, 15], + fillColor: 'blue', + fillOpacity: 0.3, + }, + tableHeader: { + bold: true, + fontSize: 13, + color: 'black', + }, + }, + defaultStyle: { + alignment: 'justify', + }, +}; + +const textDecorations: TDocumentDefinitions = { + content: [ + { text: 'Higlighted text', fontSize: 18, background: 'yellow' }, + ' ', + { + columns: [ + { text: 'Underline decoration', decoration: 'underline' }, + { text: 'Line Through decoration', decoration: 'lineThrough' }, + { text: 'Overline decoration', decoration: 'overline' }, + ], + }, + ' ', + { + columns: [ + { + text: 'Dashed style', + decoration: 'underline', + decorationStyle: 'dashed', + }, + { + text: 'Dotted style', + decoration: 'underline', + decorationStyle: 'dotted', + }, + { + text: 'Double style', + decoration: 'underline', + decorationStyle: 'double', + }, + { + text: 'Wavy style', + decoration: 'underline', + decorationStyle: 'wavy', + }, + ], + }, + ' ', + { + columns: [ + { + text: 'Using colors', + decoration: 'underline', + decorationColor: 'blue', + }, + { + text: 'Using colors', + decoration: 'lineThrough', + decorationColor: 'red', + }, + { + text: 'Using colors', + decoration: 'underline', + decorationStyle: 'wavy', + decorationColor: 'green', + }, + ], + }, + ], +}; + +const toc: TDocumentDefinitions = { + content: [ + { + text: 'This is a TOC example. Text elements marked with tocItem: true will be located in the toc. See below.', + pageBreak: 'after', + }, + { + toc: { + title: { text: 'INDEX', style: 'header' }, + textMargin: [0, 0, 0, 0], + textStyle: { italics: true }, + numberStyle: { bold: true }, + }, + }, + { + text: 'This is a header, using header style', + style: 'header', + tocItem: true, + tocStyle: { italics: true }, + tocMargin: [0, 10, 0, 0], + tocNumberStyle: { italics: true, decoration: 'underline' }, + pageBreak: 'before', + }, + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam.\n\n', + { + text: 'Subheader 1 - using subheader style', + style: 'subheader', + tocItem: true, + pageBreak: 'before', + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n', + { + text: 'Subheader 2 - using subheader style', + style: 'subheader', + tocItem: true, + pageBreak: 'before', + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n', + { + // tslint:disable-next-line: max-line-length + text: 'It is possible to apply multiple styles, by passing an array. This paragraph uses two styles: quote and small. When multiple styles are provided, they are evaluated in the specified order which is important in case they define the same properties', + style: ['quote', 'small'], + }, + { + text: [ + { + text: 'Subheader 3 - using inline text', + style: 'subheader', + tocItem: true, + }, + { + text: '; and this text not be displayed in ToC', + italics: true, + }, + ], + pageBreak: 'before', + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + ], + styles: { + header: { + fontSize: 18, + bold: true, + }, + subheader: { + fontSize: 15, + bold: true, + }, + quote: { + italics: true, + }, + small: { + fontSize: 8, + }, + }, +}; + +const vectors: TDocumentDefinitions = { + content: [ + { + text: [ + 'This ', + { text: 'is', color: 'green' }, + ' the first ', + { text: 'paragraph', color: 'red' }, + ], + }, + { + canvas: [ + { + type: 'rect', + x: 0, + y: 0, + w: 310, + h: 260, + r: 5, + dash: { length: 5 }, + lineWidth: 10, + lineColor: 'blue', + }, + { + type: 'rect', + x: 1, + y: 1, + w: 308, + h: 258, + r: 4, + lineColor: 'red', + color: '#ffffe0', + }, + { + type: 'polyline', + lineWidth: 3, + closePath: true, + points: [ + { x: 10, y: 10 }, + { x: 35, y: 40 }, + { x: 100, y: 40 }, + { x: 125, y: 10 }, + ], + }, + { + type: 'polyline', + lineWidth: 2, + color: 'blue', + lineColor: 'red', + points: [ + { x: 10, y: 110 }, + { x: 35, y: 140 }, + { x: 100, y: 140 }, + { x: 125, y: 110 }, + { x: 10, y: 110 }, + ], + }, + { + type: 'line', + x1: 40, + y1: 60, + x2: 260, + y2: 60, + lineWidth: 3, + }, + { + type: 'line', + x1: 40, + y1: 80, + x2: 260, + y2: 80, + lineWidth: 10, + lineCap: 'round', + }, + { + type: 'line', + x1: 40, + y1: 100, + x2: 260, + y2: 100, + lineWidth: 10, + lineCap: 'square', + }, + { + type: 'ellipse', + x: 150, + y: 140, + color: 'red', + fillOpacity: 0.5, + r1: 80, + r2: 60, + }, + { + type: 'rect', + x: 150, + y: 200, + w: 150, + h: 50, + }, + { + type: 'rect', + x: 10, + y: 200, + w: 100, + h: 10, + linearGradient: ['red', 'blue'], + }, + { + type: 'rect', + x: 10, + y: 215, + w: 100, + h: 10, + linearGradient: ['red', 'green', 'blue'], + }, + { + type: 'rect', + x: 10, + y: 230, + w: 100, + h: 10, + linearGradient: ['red', 'yellow', 'green', 'blue'], + }, + { + type: 'ellipse', + x: 260, + y: 140, + r1: 30, + r2: 20, + linearGradient: ['red', 'green', 'blue', 'red'], + }, + ], + }, + 'This text should be rendered under canvas', + { + color: 'black', + + text: ['This should be black '], + }, + ], + defaultStyle: { + color: 'gray', + }, +}; + +const watermark: TDocumentDefinitions = { + watermark: { + text: 'test watermark', + color: 'blue', + opacity: 0.3, + bold: true, + italics: false, + }, + content: [ + 'Test page of watermark.\n\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec id semper massa, nec dapibus mauris. Mauris in mattis nibh. Aenean feugiat volutpat aliquam. Donec sed tellus feugiat, dignissim lectus id, eleifend tortor. Ut at mauris vel dui euismod accumsan. Cras sodales, ante sit amet varius dapibus, dolor neque finibus justo, vel ornare arcu dolor vitae tellus. Aenean faucibus egestas urna in interdum. Mauris convallis dolor a condimentum sagittis. Suspendisse non laoreet nisl. Curabitur sed pharetra ipsum. Curabitur aliquet purus vitae pharetra tincidunt. Cras aliquam tempor justo sit amet euismod. Praesent risus magna, lobortis eget dictum sit amet, tristique vel enim. Duis aliquet, urna maximus sollicitudin lobortis, mi nunc dignissim ligula, et lacinia magna leo non sem.', + ], +}; +const watermark2: TDocumentDefinitions = { + watermark: 'test watermark', + content: [ + 'Test page of watermark.\n\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec id semper massa, nec dapibus mauris. Mauris in mattis nibh. Aenean feugiat volutpat aliquam. Donec sed tellus feugiat, dignissim lectus id, eleifend tortor. Ut at mauris vel dui euismod accumsan. Cras sodales, ante sit amet varius dapibus, dolor neque finibus justo, vel ornare arcu dolor vitae tellus. Aenean faucibus egestas urna in interdum. Mauris convallis dolor a condimentum sagittis. Suspendisse non laoreet nisl. Curabitur sed pharetra ipsum. Curabitur aliquet purus vitae pharetra tincidunt. Cras aliquam tempor justo sit amet euismod. Praesent risus magna, lobortis eget dictum sit amet, tristique vel enim. Duis aliquet, urna maximus sollicitudin lobortis, mi nunc dignissim ligula, et lacinia magna leo non sem.', + ], +}; diff --git a/types/pdfmake/test/pdfmake-global-tests.ts b/types/pdfmake/test/pdfmake-global-tests.ts new file mode 100644 index 0000000000..bd5695c48f --- /dev/null +++ b/types/pdfmake/test/pdfmake-global-tests.ts @@ -0,0 +1,20 @@ +const fonts = { + Roboto: { + normal: 'Roboto-Regular.ttf', + bold: 'Roboto-Medium.ttf', + italics: 'Roboto-Italic.ttf', + bolditalics: 'Roboto-MediumItalic.ttf', + }, +}; + +pdfMake.fonts = fonts; + +const dd = { + content: 'Hello world!', +}; + +// $ExpectType TCreatedPdf +pdfMake.createPdf(dd); + +// $ExpectType TCreatedPdf +pdfMake.createPdf(dd, {}, fonts); diff --git a/types/pdfmake/test/pdfmake-import-default-tests.ts b/types/pdfmake/test/pdfmake-import-default-tests.ts new file mode 100644 index 0000000000..8c423cf489 --- /dev/null +++ b/types/pdfmake/test/pdfmake-import-default-tests.ts @@ -0,0 +1,14 @@ +import pdfMake from "pdfmake/build/pdfmake"; +import pdfFonts from "pdfmake/build/vfs_fonts"; + +pdfMake.vfs = pdfFonts.pdfMake.vfs; + +const dd = { + content: 'Hello world!' +}; + +// $ExpectType TCreatedPdf +pdfMake.createPdf(dd); + +// $ExpectType TCreatedPdf +pdfMake.createPdf(dd, {}, fonts); diff --git a/types/pdfmake/test/pdfmake-interfaces-tests.ts b/types/pdfmake/test/pdfmake-interfaces-tests.ts new file mode 100644 index 0000000000..94f317c3bb --- /dev/null +++ b/types/pdfmake/test/pdfmake-interfaces-tests.ts @@ -0,0 +1,238 @@ +import { + Content, + ContentImage, + ContentOrderedList, + ContentSvg, + ContentUnorderedList, + TDocumentDefinitions, +} from 'pdfmake/interfaces'; + +const createContent: () => Content = () => 'allo'; +const content: Content = createContent(); + +if (typeof content !== 'string' && 'stack' in content) { + // $ExpectType ContentStack + content; +} + +const staticBackground: TDocumentDefinitions = { + content: 'Content', + background: 'Static Background', +}; + +const noCompress: TDocumentDefinitions = { + content: 'Content', + compress: false, +}; + +const documentMetadata: TDocumentDefinitions = { + info: { + title: 'awesome Document', + author: 'john doe', + subject: 'subject of document', + keywords: 'keywords for document', + creator: 'pdfmake', + producer: 'pdfmake', + creationDate: new Date('1970-01-01'), + modDate: new Date('2020-02-29'), + trapped: 'true', + }, + content: 'This is an sample PDF printed with pdfMake', +}; + +const dynamicHeaderFooter: TDocumentDefinitions = { + footer: (currentPage, pageCount) => `${currentPage} of ${pageCount}`, + header: (currentPage, pageCount, pageSize) => [ + // you can apply any logic and return any valid pdfmake element + { text: 'simple text', alignment: currentPage % 2 ? 'left' : 'right' }, + { canvas: [{ type: 'rect', x: 170, y: 32, w: pageSize.width - 170, h: 40 }] }, + ], + content: 'This is an sample PDF printed with pdfMake', +}; + +const staticHeaderFooter: TDocumentDefinitions = { + header: 'simple text', + footer: { + columns: ['Left part', { text: 'Right part', alignment: 'right' }], + }, + content: 'This is an sample PDF printed with pdfMake', +}; + +const pageOrientation: TDocumentDefinitions = { + pageOrientation: 'portrait', + content: [ + { text: 'Text on Portrait' }, + { text: 'Text on Landscape', pageOrientation: 'landscape', pageBreak: 'before' }, + { text: 'Text on Landscape 2', pageOrientation: 'portrait', pageBreak: 'after' }, + { text: 'Text on Portrait 2' }, + ], +}; + +const autoPageHeight: TDocumentDefinitions = { + pageSize: { + width: 595.28, + height: 'auto', + }, + content: 'This is an sample PDF printed with pdfMake', +}; + +const pageBreakBefore: TDocumentDefinitions = { + content: [ + { text: '1 Headline', headlineLevel: 1 }, + 'Some long text of variable length ...', + { text: '2 Headline', headlineLevel: 1 }, + 'Some long text of variable length ...', + { text: '3 Headline', headlineLevel: 1 }, + 'Some long text of variable length ...', + ], + pageBreakBefore: (currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage) => + currentNode.headlineLevel === 1 && followingNodesOnPage.length === 0, +}; + +const qrCodes: TDocumentDefinitions = { + content: [ + { qr: 'text in QR' }, + { qr: 'text in QR', foreground: 'red', background: 'yellow' }, + { qr: 'text in QR', fit: 500 }, + { qr: 'text in QR', version: -1 }, + { qr: 'text in QR', version: 1 }, + { qr: 'text in QR', version: 40 }, + { qr: 'text in QR', eccLevel: 'L' }, + { qr: 'text in QR', eccLevel: 'M' }, + { qr: 'text in QR', eccLevel: 'Q' }, + { qr: 'text in QR', eccLevel: 'H' }, + { qr: 'text in QR', mode: 'numeric' }, + { qr: 'text in QR', mode: 'alphanumeric' }, + { qr: 'text in QR', mode: 'octet' }, + { qr: 'text in QR', mask: -1 }, + { qr: 'text in QR', mask: 0 }, + { qr: 'text in QR', mask: 7 }, + ], +}; + +const watermark: TDocumentDefinitions = { + watermark: { + text: 'test watermark', + color: 'blue', + opacity: 0.3, + bold: true, + italics: false, + font: 'Roboto', + fontSize: 15, + angle: 30, + }, + content: ['...'], +}; + +const fontsUsage: TDocumentDefinitions = { + content: [ + { text: 'First paragraph', font: 'Times' }, + { + text: 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines', + }, + ], + defaultStyle: { + font: 'Helvetica', + }, +}; + +const securityVersion: TDocumentDefinitions = { + content: 'Content', + userPassword: 'hunter2', + permissions: { + printing: 'lowResolution', + }, + version: '1.5', +}; + +const allPageSizes: TDocumentDefinitions[] = [ + { content, pageSize: '4A0' }, + { content, pageSize: '2A0' }, + { content, pageSize: 'A0' }, + { content, pageSize: 'A1' }, + { content, pageSize: 'A2' }, + { content, pageSize: 'A3' }, + { content, pageSize: 'A4' }, + { content, pageSize: 'A5' }, + { content, pageSize: 'A6' }, + { content, pageSize: 'A7' }, + { content, pageSize: 'A8' }, + { content, pageSize: 'A9' }, + { content, pageSize: 'A10' }, + { content, pageSize: 'B0' }, + { content, pageSize: 'B1' }, + { content, pageSize: 'B2' }, + { content, pageSize: 'B3' }, + { content, pageSize: 'B4' }, + { content, pageSize: 'B5' }, + { content, pageSize: 'B6' }, + { content, pageSize: 'B7' }, + { content, pageSize: 'B8' }, + { content, pageSize: 'B9' }, + { content, pageSize: 'B10' }, + { content, pageSize: 'C0' }, + { content, pageSize: 'C1' }, + { content, pageSize: 'C2' }, + { content, pageSize: 'C3' }, + { content, pageSize: 'C4' }, + { content, pageSize: 'C5' }, + { content, pageSize: 'C6' }, + { content, pageSize: 'C7' }, + { content, pageSize: 'C8' }, + { content, pageSize: 'C9' }, + { content, pageSize: 'C10' }, + { content, pageSize: 'RA1' }, + { content, pageSize: 'RA2' }, + { content, pageSize: 'RA3' }, + { content, pageSize: 'RA4' }, + { content, pageSize: 'SRA1' }, + { content, pageSize: 'SRA2' }, + { content, pageSize: 'SRA3' }, + { content, pageSize: 'SRA4' }, + { content, pageSize: 'EXECUTIVE' }, + { content, pageSize: 'FOLIO' }, + { content, pageSize: 'LEGAL' }, + { content, pageSize: 'LETTER' }, + { content, pageSize: 'TABLOID' }, +]; + +let ol: ContentOrderedList = { + ol: ['1', '2', '3'], + markerColor: 'blue', +}; +ol = { ol: ['1'], type: 'lower-alpha' }; +ol = { ol: ['1'], type: 'upper-alpha' }; +ol = { ol: ['1'], type: 'lower-roman' }; +ol = { ol: ['1'], type: 'upper-roman' }; +ol = { ol: ['1'], type: 'none' }; + +let ul: ContentUnorderedList = { + ul: ['1', '2', '3'], + markerColor: 'blue', +}; + +ul = { ul: ['1'], type: 'square' }; +ul = { ul: ['1'], type: 'circle' }; +ul = { ul: ['1'], type: 'none' }; + +const svg1: ContentSvg = { + svg: 'test', + width: 5, + height: 5, +}; + +const svg2: ContentSvg = { + svg: 'test', + fit: [50, 50], +}; + +const image1: ContentImage = { + image: 'test', + width: 5, + height: 5, +}; + +const image2: ContentImage = { + image: 'test', + fit: [50, 50], +}; diff --git a/types/pdfmake/test/pdfmake-module-browser-tests.ts b/types/pdfmake/test/pdfmake-module-browser-tests.ts new file mode 100644 index 0000000000..0e675bdf84 --- /dev/null +++ b/types/pdfmake/test/pdfmake-module-browser-tests.ts @@ -0,0 +1,46 @@ +import pdfFonts = require('pdfmake/build/vfs_fonts'); +import pdfMake = require('pdfmake/build/pdfmake'); +import { BufferOptions } from 'pdfmake/interfaces'; + +pdfMake.vfs = pdfFonts.pdfMake.vfs; + +const dd = { + content: 'Hello world!' +}; + +const options: BufferOptions = { + fontLayoutCache: true, + bufferPages: true +}; + +pdfMake.createPdf(dd).download(); +pdfMake.createPdf(dd).download('defaultFileName'); +pdfMake.createPdf(dd).download('defaultFileName', () => { + console.log('Download finished'); +}); +pdfMake.createPdf(dd).download('defaultFileName', undefined, options); +pdfMake.createPdf(dd).download(() => { + console.log('Download finished'); +}); +pdfMake.createPdf(dd).download(() => { + console.log('Download finished'); +}, options); + +pdfMake.createPdf(dd).open(); +pdfMake.createPdf(dd).open(options); +const win = window.open('', '_blank'); +pdfMake.createPdf(dd).open({}, win); +pdfMake.createPdf(dd).open({}, window); + +pdfMake.createPdf(dd).print(); +pdfMake.createPdf(dd).print(options); +pdfMake.createPdf(dd).print({}, win); +pdfMake.createPdf(dd).print({}, window); + +const pdfDocGenerator = pdfMake.createPdf(dd); +pdfDocGenerator.getDataUrl((dataUrl) => { + const targetElement = document.querySelector('#iframeContainer'); + const iframe = document.createElement('iframe'); + iframe.src = dataUrl; + targetElement!.appendChild(iframe); +}); diff --git a/types/pdfmake/test/pdfmake-module-server-tests.ts b/types/pdfmake/test/pdfmake-module-server-tests.ts new file mode 100644 index 0000000000..1ace059a72 --- /dev/null +++ b/types/pdfmake/test/pdfmake-module-server-tests.ts @@ -0,0 +1,33 @@ +import PdfPrinter = require('pdfmake'); +import { + BufferOptions, + TDocumentDefinitions, + TFontDictionary, +} from 'pdfmake/interfaces'; + +const fonts: TFontDictionary = { + Roboto: { + normal: 'fonts/Roboto-Regular.ttf', + bold: 'fonts/Roboto-Medium.ttf', + italics: 'fonts/Roboto-Italic.ttf', + bolditalics: 'fonts/Roboto-MediumItalic.ttf', + }, +}; + +const printer = new PdfPrinter(fonts); + +const dd: TDocumentDefinitions = { + content: 'Hello world!', +}; + +const options: BufferOptions = { + fontLayoutCache: true, + bufferPages: true, + tableLayouts: 'noBorders', + autoPrint: true, + progressCallback: progress => + console.log('Creating pdf: ', progress * 100, '%...'), +}; + +// $ExpectType PDFDocument +printer.createPdfKitDocument(dd, options); diff --git a/types/pdfmake/test/pdfmake-playground-examples-tests.ts b/types/pdfmake/test/pdfmake-playground-examples-tests.ts new file mode 100644 index 0000000000..25c1db43d7 --- /dev/null +++ b/types/pdfmake/test/pdfmake-playground-examples-tests.ts @@ -0,0 +1,1438 @@ +import { TDocumentDefinitions } from 'pdfmake/interfaces'; + +const basics: TDocumentDefinitions = { + content: [ + 'First paragraph', + 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines', + ], +}; + +const nameStyles: TDocumentDefinitions = { + content: [ + { + text: 'This is a header, using header style', + style: 'header', + }, + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam.\n\n', + { + text: 'Subheader 1 - using subheader style', + style: 'subheader', + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n', + { + text: 'Subheader 2 - using subheader style', + style: 'subheader', + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Confectum ponit legam, perferendis nomine miserum, animi. Moveat nesciunt triari naturam posset, eveniunt specie deorsus efficiat sermone instituendarum fuisse veniat, eademque mutat debeo. Delectet plerique protervi diogenem dixerit logikh levius probabo adipiscuntur afficitur, factis magistra inprobitatem aliquo andriam obiecta, religionis, imitarentur studiis quam, clamat intereant vulgo admonitionem operis iudex stabilitas vacillare scriptum nixam, reperiri inveniri maestitiam istius eaque dissentias idcirco gravis, refert suscipiet recte sapiens oportet ipsam terentianus, perpauca sedatio aliena video.\n\n', + { + // tslint:disable-next-line: max-line-length + text: 'It is possible to apply multiple styles, by passing an array. This paragraph uses two styles: quote and small. When multiple styles are provided, they are evaluated in the specified order which is important in case they define the same properties', + style: ['quote', 'small'], + }, + ], + styles: { + header: { + fontSize: 18, + bold: true, + }, + subheader: { + fontSize: 15, + bold: true, + }, + quote: { + italics: true, + }, + small: { + fontSize: 8, + }, + }, +}; + +const inlineStyling: TDocumentDefinitions = { + content: [ + { + text: 'This is a header (whole paragraph uses the same header style)\n\n', + style: 'header', + }, + { + text: [ + 'It is however possible to provide an array of texts ', + 'to the paragraph (instead of a single string) and have ', + { text: 'a better ', fontSize: 15, bold: true }, + 'control over it. \nEach inline can be ', + { text: 'styled ', fontSize: 20 }, + { text: 'independently ', italics: true, fontSize: 40 }, + 'then.\n\n', + ], + }, + { text: 'Mixing named styles and style-overrides', style: 'header' }, + { + style: 'bigger', + italics: false, + text: [ + 'We can also mix named-styles and style-overrides at both paragraph and inline level. ', + 'For example, this paragraph uses the "bigger" style, which changes fontSize to 15 and sets italics to true. ', + "Texts are not italics though. It's because we've overriden italics back to false at ", + 'the paragraph level. \n\n', + "We can also change the style of a single inline. Let's use a named style called header: ", + { text: 'like here.\n', style: 'header' }, + 'It got bigger and bold.\n\n', + "OK, now we're going to mix named styles and style-overrides at the inline level. ", + "We'll use header style (it makes texts bigger and bold), but we'll override ", + 'bold back to false: ', + { text: 'wow! it works!', style: 'header', bold: false }, + "\n\nMake sure to take a look into the sources to understand what's going on here.", + ], + }, + ], + styles: { + header: { + fontSize: 18, + bold: true, + }, + bigger: { + fontSize: 15, + italics: true, + }, + }, +}; + +const styleOverrides: TDocumentDefinitions = { + content: [ + { + text: 'This paragraph uses header style and extends the alignment property', + style: 'header', + alignment: 'center', + }, + { + text: [ + 'This paragraph uses header style and overrides bold value setting it back to false.\n', + 'Header style in this example sets alignment to justify, so this paragraph should be rendered \n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + ], + style: 'header', + bold: false, + }, + ], + styles: { + header: { + fontSize: 18, + bold: true, + alignment: 'justify', + }, + }, +}; + +const columns: TDocumentDefinitions = { + content: [ + 'By default paragraphs are stacked one on top of (or actually - below) another. ', + "It's possible however to split any paragraph (or even the whole document) into columns.\n\n", + 'Here we go with 2 star-sized columns, with justified text and gap set to 20:\n\n', + { + alignment: 'justify', + columns: [ + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + ], + }, + "\nStar-sized columns have always equal widths, so if we define 3 of those, it'll look like this (make sure to scroll to the next page, as we have a couple of more examples):\n\n", + { + columns: [ + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + ], + }, + // tslint:disable-next-line: max-line-length + "\nYou can also specify accurate widths for some (or all columns). Let's make the first column and the last one narrow and let the layout engine divide remaining space equally between other star-columns:\n\n", + { + columns: [ + { + width: 90, + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + width: '*', + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + width: '*', + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + width: 90, + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + ], + }, + '\nWe also support auto columns. They set their widths based on the content:\n\n', + { + columns: [ + { + width: 'auto', + text: 'auto column', + }, + { + width: '*', + text: 'This is a star-sized column. It should get the remaining space divided by the number of all star-sized columns.', + }, + { + width: 50, + text: 'this one has specific width set to 50', + }, + { + width: 'auto', + text: 'another auto column', + }, + { + width: '*', + text: 'This is a star-sized column. It should get the remaining space divided by the number of all star-sized columns.', + }, + ], + }, + '\nIf all auto columns fit within available width, the table does not occupy whole space:\n\n', + { + columns: [ + { + width: 'auto', + text: 'val1', + }, + { + width: 'auto', + text: 'val2', + }, + { + width: 'auto', + text: 'value3', + }, + { + width: 'auto', + text: 'value 4', + }, + ], + }, + // tslint:disable-next-line: max-line-length + '\nAnother cool feature of pdfmake is the ability to have nested elements. Each column is actually quite similar to the whole document, so we can have inner paragraphs and further divisions, like in the following example:\n\n', + { + columns: [ + { + width: 100, + fontSize: 9, + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Conveniunt quieti extremum severitatem disseretur virtute locum virtus declarant. Greges telos detrimenti persius possint eripuit appellat democrito suscipere existimant. Facere usus levitatibus confirmavit, provincia rutilius libris accommodare valetudinis ignota fugienda arbitramur falsarum commodius. Voluptas summis arbitrarer cognitio temperantiamque, fuit posidonium pro assueverit animos inferiorem, affecti honestum ferreum cum tot nemo ius partes dissensio opinor, tuum intellegunt numeris ignorant, odia diligenter licet, sublatum repellere, maior ficta severa quantum mortem. Aut evertitur impediri vivamus.', + }, + [ + // tslint:disable-next-line: max-line-length + "As you can see in the document definition - this column is not defined with an object, but an array, which means it's treated as an array of paragraphs rendered one below another.", + "Just like on the top-level of the document. Let's try to divide the remaing space into 3 star-sized columns:\n\n", + { + columns: [ + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + { + // tslint:disable-next-line: max-line-length + text: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.', + }, + ], + }, + ], + ], + }, + "\n\nOh, don't forget, we can use everything from styling examples (named styles, custom overrides) here as well.\n\n", + "For instance - our next paragraph will use the 'bigger' style (with fontSize set to 15 and italics - true). We'll split it into three columns and make sure they inherit the style:\n\n", + { + style: 'bigger', + columns: [ + "First column (BTW - it's defined as a single string value. pdfmake will turn it into appropriate structure automatically and make sure it inherits the styles", + { + fontSize: 20, + text: "In this column, we've overriden fontSize to 20. It means the content should have italics=true (inherited from the style) and be a little bit bigger", + }, + { + style: 'header', + // tslint:disable-next-line: max-line-length + text: "Last column does not override any styling properties, but applies a new style (header) to itself. Eventually - texts here have italics=true (from bigger) and derive fontSize from the style. OK, but which one? Both styles define it. As we already know from our styling examples, multiple styles can be applied to the element and their order is important. Because 'header' style has been set after 'bigger' its fontSize takes precedence over the fontSize from 'bigger'. This is how it works. You will find more examples in the unit tests.", + }, + ], + }, + "\n\nWow, you've read the whole document! Congratulations :D", + ], + styles: { + header: { + fontSize: 18, + bold: true, + }, + bigger: { + fontSize: 15, + italics: true, + }, + }, + defaultStyle: { + columnGap: 20, + }, +}; + +const tables: TDocumentDefinitions = { + content: [ + { text: 'Tables', style: 'header' }, + 'Official documentation is in progress, this document is just a glimpse of what is possible with pdfmake and its layout engine.', + { text: 'A simple table (no headers, no width specified, no spans, no styling)', style: 'subheader' }, + 'The following table has nothing more than a body array', + { + style: 'tableExample', + table: { + body: [ + ['Column 1', 'Column 2', 'Column 3'], + ['One value goes here', 'Another one here', 'OK?'], + ], + }, + }, + { text: 'A simple table with nested elements', style: 'subheader' }, + 'It is of course possible to nest any other type of nodes available in pdfmake inside table cells', + { + style: 'tableExample', + table: { + body: [ + ['Column 1', 'Column 2', 'Column 3'], + [ + { + stack: [ + "Let's try an unordered list", + { + ul: ['item 1', 'item 2'], + }, + ], + }, + [ + 'or a nested table', + { + table: { + body: [ + ['Col1', 'Col2', 'Col3'], + ['1', '2', '3'], + ['1', '2', '3'], + ], + }, + }, + ], + { + text: [ + 'Inlines can be ', + { text: 'styled\n', italics: true }, + { text: 'easily as everywhere else', fontSize: 10 }, + ], + }, + ], + ], + }, + }, + { text: 'Defining column widths', style: 'subheader' }, + 'Tables support the same width definitions as standard columns:', + { + bold: true, + ul: ['auto', 'star', 'fixed value'], + }, + { + style: 'tableExample', + table: { + widths: [100, '*', 200, '*'], + body: [ + ['width=100', 'star-sized', 'width=200', 'star-sized'], + [ + 'fixed-width cells have exactly the specified width', + { text: 'nothing interesting here', italics: true, color: 'gray' }, + { text: 'nothing interesting here', italics: true, color: 'gray' }, + { text: 'nothing interesting here', italics: true, color: 'gray' }, + ], + ], + }, + }, + { + style: 'tableExample', + table: { + widths: ['*', 'auto'], + body: [ + [ + 'This is a star-sized column. The next column over, an auto-sized column, will wrap to accomodate all the text in this cell.', + 'I am auto sized.', + ], + ], + }, + }, + { + style: 'tableExample', + table: { + widths: ['*', 'auto'], + body: [ + [ + 'This is a star-sized column. The next column over, an auto-sized column, will not wrap to accomodate all the text in this cell, because it has been given the noWrap style.', + { text: 'I am auto sized.', noWrap: true }, + ], + ], + }, + }, + { text: 'Defining row heights', style: 'subheader' }, + { + style: 'tableExample', + table: { + heights: [20, 50, 70], + body: [ + ['row 1 with height 20', 'column B'], + ['row 2 with height 50', 'column B'], + ['row 3 with height 70', 'column B'], + ], + }, + }, + 'With same height:', + { + style: 'tableExample', + table: { + heights: 40, + body: [ + ['row 1', 'column B'], + ['row 2', 'column B'], + ['row 3', 'column B'], + ], + }, + }, + 'With height from function:', + { + style: 'tableExample', + table: { + heights(row) { + return (row + 1) * 25; + }, + body: [ + ['row 1', 'column B'], + ['row 2', 'column B'], + ['row 3', 'column B'], + ], + }, + }, + { text: 'Column/row spans', pageBreak: 'before', style: 'subheader' }, + 'Each cell-element can set a rowSpan or colSpan', + { + style: 'tableExample', + color: '#444', + table: { + widths: [200, 'auto', 'auto'], + headerRows: 2, + keepWithHeaderRows: 1, + body: [ + [ + { text: 'Header with Colspan = 2', style: 'tableHeader', colSpan: 2, alignment: 'center' }, + {}, + { text: 'Header 3', style: 'tableHeader', alignment: 'center' }, + ], + [ + { text: 'Header 1', style: 'tableHeader', alignment: 'center' }, + { text: 'Header 2', style: 'tableHeader', alignment: 'center' }, + { text: 'Header 3', style: 'tableHeader', alignment: 'center' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + [ + { + rowSpan: 3, + text: 'rowSpan set to 3\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor', + }, + 'Sample value 2', + 'Sample value 3', + ], + ['', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + [ + 'Sample value 1', + { colSpan: 2, rowSpan: 2, text: 'Both:\nrowSpan and colSpan\ncan be defined at the same time' }, + '', + ], + ['Sample value 1', '', ''], + ], + }, + }, + { text: 'Headers', pageBreak: 'before', style: 'subheader' }, + 'You can declare how many rows should be treated as a header. Headers are automatically repeated on the following pages', + { + text: [ + // tslint:disable-next-line: max-line-length + "It is also possible to set keepWithHeaderRows to make sure there will be no page-break between the header and these rows. Take a look at the document-definition and play with it. If you set it to one, the following table will automatically start on the next page, since there's not enough space for the first row to be rendered here", + ], + color: 'gray', + italics: true, + }, + { + style: 'tableExample', + table: { + headerRows: 1, + dontBreakRows: true, + keepWithHeaderRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + [ + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', + ], + ], + }, + }, + { text: 'Styling tables', style: 'subheader' }, + 'You can provide a custom styler for the table. Currently it supports:', + { + ul: ['line widths', 'line colors', 'cell paddings'], + }, + 'with more options coming soon...\n\npdfmake currently has a few predefined styles (see them on the next page)', + { text: 'noBorders:', fontSize: 14, bold: true, pageBreak: 'before', margin: [0, 0, 0, 8] }, + { + style: 'tableExample', + table: { + headerRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: 'noBorders', + }, + { text: 'headerLineOnly:', fontSize: 14, bold: true, margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + headerRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: 'headerLineOnly', + }, + { text: 'lightHorizontalLines:', fontSize: 14, bold: true, margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + headerRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: 'lightHorizontalLines', + }, + { text: 'but you can provide a custom styler as well', margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + headerRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: { + hLineWidth(i, node) { + return i === 0 || i === node.table.body.length ? 2 : 1; + }, + vLineWidth(i, node) { + return i === 0 || i === node.table.widths!.length ? 2 : 1; + }, + hLineColor(i, node) { + return i === 0 || i === node.table.body.length ? 'black' : 'gray'; + }, + vLineColor(i, node) { + return i === 0 || i === node.table.widths!.length ? 'black' : 'gray'; + }, + hLineStyle(i, node) { return {dash: { length: 10, space: 4 }}; }, + vLineStyle(i, node) { return {dash: { length: 10, space: 4 }}; }, + paddingLeft(i, node) { return 4; }, + paddingRight(i, node) { return 4; }, + paddingTop(i, node) { return 2; }, + paddingBottom(i, node) { return 2; }, + fillColor(i, node) { return null; } + }, + }, + { text: 'zebra style', margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + body: [ + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: { + fillColor(rowIndex, node, columnIndex) { + return rowIndex % 2 === 0 ? '#CCCCCC' : null; + }, + }, + }, + { text: 'handling fill color opacity...', margin: [0, 20, 0, 8] }, + { text: '... just hardcoding values in the second row', margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + body: [ + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + [ + { text: 'Sample value 1', fillOpacity: 0.15, fillColor: 'blue' }, + { text: 'Sample value 2', fillOpacity: 0.6, fillColor: 'blue' }, + { text: 'Sample value 3', fillOpacity: 0.85, fillColor: 'blue' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + }, + { text: '... using a custom styler and overriding it in the second row', margin: [0, 20, 0, 8] }, + { + style: 'tableOpacityExample', + table: { + body: [ + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + [ + { text: 'Sample value 1', fillOpacity: 0.15 }, + { text: 'Sample value 2', fillOpacity: 0.6 }, + { text: 'Sample value 3', fillOpacity: 0.85 }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + }, + { text: '... with a function (opacity at 0 means fully transparent, i.e no color)', margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + body: [ + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: { + fillColor: 'blue', + fillOpacity(rowIndex, node, columnIndex) { + return rowIndex / 8 + columnIndex / 3; + }, + }, + }, + { text: 'and can be used dash border', margin: [0, 20, 0, 8] }, + { + style: 'tableExample', + table: { + headerRows: 1, + body: [ + [ + { text: 'Header 1', style: 'tableHeader' }, + { text: 'Header 2', style: 'tableHeader' }, + { text: 'Header 3', style: 'tableHeader' }, + ], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ['Sample value 1', 'Sample value 2', 'Sample value 3'], + ], + }, + layout: { + hLineWidth(i, node) { + return i === 0 || i === node.table.body.length ? 2 : 1; + }, + vLineWidth(i, node) { + return i === 0 || i === node.table.widths!.length ? 2 : 1; + }, + hLineColor(i, node) { + return 'black'; + }, + vLineColor(i, node) { + return 'black'; + }, + hLineStyle(i, node) { + if (i === 0 || i === node.table.body.length) { + return null; + } + return { dash: { length: 10, space: 4 } }; + }, + vLineStyle(i, node) { + if (i === 0 || i === node.table.widths!.length) { + return null; + } + return { dash: { length: 4 } }; + }, + paddingLeft(i, node) { + return 4; + }, + paddingRight(i, node) { + return 4; + }, + paddingTop(i, node) { + return 2; + }, + paddingBottom(i, node) { + return 2; + }, + fillColor(i, node) { + return null; + }, + }, + }, + { text: 'Optional border', fontSize: 14, bold: true, pageBreak: 'before', margin: [0, 0, 0, 8] }, + 'Each cell contains an optional border property: an array of 4 booleans for left border, top border, right border, bottom border.', + { + style: 'tableExample', + table: { + body: [ + [ + { + border: [false, true, false, false], + fillColor: '#eeeeee', + text: 'border:\n[false, true, false, false]', + }, + { + border: [false, false, false, false], + fillColor: '#dddddd', + text: 'border:\n[false, false, false, false]', + }, + { + border: [true, true, true, true], + fillColor: '#eeeeee', + text: 'border:\n[true, true, true, true]', + }, + ], + [ + { + rowSpan: 3, + border: [true, true, true, true], + fillColor: '#eeeeff', + text: 'rowSpan: 3\n\nborder:\n[true, true, true, true]', + }, + { + border: undefined, + fillColor: '#eeeeee', + text: 'border:\nundefined', + }, + { + border: [true, false, false, false], + fillColor: '#dddddd', + text: 'border:\n[true, false, false, false]', + }, + ], + [ + '', + { + colSpan: 2, + border: [true, true, true, true], + fillColor: '#eeffee', + text: 'colSpan: 2\n\nborder:\n[true, true, true, true]', + }, + '', + ], + [ + '', + { + border: undefined, + fillColor: '#eeeeee', + text: 'border:\nundefined', + }, + { + border: [false, false, true, true], + fillColor: '#dddddd', + text: 'border:\n[false, false, true, true]', + }, + ], + ], + }, + layout: { + defaultBorder: false, + }, + }, + // tslint:disable-next-line: max-line-length + 'For every cell without a border property, whether it has all borders or not is determined by layout.defaultBorder, which is false in the table above and true (by default) in the table below.', + { + style: 'tableExample', + table: { + body: [ + [ + { + border: [false, false, false, false], + fillColor: '#eeeeee', + text: 'border:\n[false, false, false, false]', + }, + { + fillColor: '#dddddd', + text: 'border:\nundefined', + }, + { + fillColor: '#eeeeee', + text: 'border:\nundefined', + }, + ], + [ + { + fillColor: '#dddddd', + text: 'border:\nundefined', + }, + { + fillColor: '#eeeeee', + text: 'border:\nundefined', + }, + { + border: [true, true, false, false], + fillColor: '#dddddd', + text: 'border:\n[true, true, false, false]', + }, + ], + ], + }, + }, + 'And some other examples with rowSpan/colSpan...', + { + style: 'tableExample', + table: { + body: [ + ['', 'column 1', 'column 2', 'column 3'], + [ + 'row 1', + { + rowSpan: 3, + colSpan: 3, + border: [true, true, true, true], + fillColor: '#cccccc', + text: 'rowSpan: 3\ncolSpan: 3\n\nborder:\n[true, true, true, true]', + }, + '', + '', + ], + ['row 2', '', '', ''], + ['row 3', '', '', ''], + ], + }, + layout: { + defaultBorder: false, + }, + }, + { + style: 'tableExample', + table: { + body: [ + [ + { + colSpan: 3, + text: 'colSpan: 3\n\nborder:\n[false, false, false, false]', + fillColor: '#eeeeee', + border: [false, false, false, false], + }, + '', + '', + ], + ['border:\nundefined', 'border:\nundefined', 'border:\nundefined'], + ], + }, + }, + { + style: 'tableExample', + table: { + body: [ + [ + { + rowSpan: 3, + text: 'rowSpan: 3\n\nborder:\n[false, false, false, false]', + fillColor: '#eeeeee', + border: [false, false, false, false], + }, + 'border:\nundefined', + 'border:\nundefined', + ], + ['', 'border:\nundefined', 'border:\nundefined'], + ['', 'border:\nundefined', 'border:\nundefined'], + ], + }, + }, + ], + styles: { + header: { + fontSize: 18, + bold: true, + margin: [0, 0, 0, 10], + }, + subheader: { + fontSize: 16, + bold: true, + margin: [0, 10, 0, 5], + }, + tableExample: { + margin: [0, 5, 0, 15], + }, + tableOpacityExample: { + margin: [0, 5, 0, 15], + fillColor: 'blue', + fillOpacity: 0.3, + }, + tableHeader: { + bold: true, + fontSize: 13, + color: 'black', + }, + }, + defaultStyle: { + alignment: 'justify', + }, +}; + +const lists: TDocumentDefinitions = { + content: [ + { text: 'Unordered list', style: 'header' }, + { + ul: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nUnordered list with longer lines', style: 'header' }, + { + ul: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'item 3', + ], + }, + { text: '\n\nOrdered list', style: 'header' }, + { + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list with longer lines', style: 'header' }, + { + ol: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'item 3', + ], + }, + { text: '\n\nOrdered list should be descending', style: 'header' }, + { + reversed: true, + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list with start value', style: 'header' }, + { + start: 50, + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list with own values', style: 'header' }, + { + ol: [ + { text: 'item 1', counter: 10 }, + { text: 'item 2', counter: 20 }, + { text: 'item 3', counter: 30 }, + { text: 'item 4 without own value' }, + ], + }, + { text: '\n\nNested lists (ordered)', style: 'header' }, + { + ol: [ + 'item 1', + [ + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + ol: [ + 'subitem 1', + 'subitem 2', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + text: [ + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 4', + 'subitem 5', + ], + }, + ], + 'item 3\nsecond line of item3', + ], + }, + { text: '\n\nNested lists (unordered)', style: 'header' }, + { + ol: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + ul: [ + 'subitem 1', + 'subitem 2', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + text: [ + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 4', + 'subitem 5', + ], + }, + 'item 3\nsecond line of item3', + ], + }, + { text: '\n\nUnordered lists inside columns', style: 'header' }, + { + columns: [ + { + ul: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + { + ul: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + ], + }, + { text: '\n\nOrdered lists inside columns', style: 'header' }, + { + columns: [ + { + ol: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + { + ol: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + ], + }, + { text: '\n\nNested lists width columns', style: 'header' }, + { + ul: [ + 'item 1', + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + ol: [ + [ + { + columns: [ + 'column 1', + { + stack: [ + 'column 2', + { + ul: [ + 'item 1', + 'item 2', + { + ul: [ + 'item', + 'item', + 'item', + ], + }, + 'item 4', + ], + }, + ], + }, + 'column 3', + 'column 4', + ], + }, + 'subitem 1 in a vertical container', + 'subitem 2 in a vertical container', + ], + 'subitem 2', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + { + text: [ + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + ], + }, + + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 3 - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit', + 'subitem 4', + 'subitem 5', + ], + }, + 'item 3\nsecond line of item3', + ], + }, + { text: '\n\nUnordered list with square marker type', style: 'header' }, + { + type: 'square', + ul: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nUnordered list with circle marker type', style: 'header' }, + { + type: 'circle', + ul: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nColored unordered list', style: 'header' }, + { + color: 'blue', + ul: ['item 1', 'item 2', 'item 3'], + }, + { + text: '\n\nColored unordered list with own marker color', + style: 'header', + }, + { + color: 'blue', + markerColor: 'red', + ul: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nColored ordered list', style: 'header' }, + { + color: 'blue', + ol: ['item 1', 'item 2', 'item 3'], + }, + { + text: '\n\nColored ordered list with own marker color', + style: 'header', + }, + { + color: 'blue', + markerColor: 'red', + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list - type: lower-alpha', style: 'header' }, + { + type: 'lower-alpha', + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list - type: upper-alpha', style: 'header' }, + { + type: 'upper-alpha', + ol: ['item 1', 'item 2', 'item 3'], + }, + + { text: '\n\nOrdered list - type: upper-roman', style: 'header' }, + { + type: 'upper-roman', + ol: ['item 1', 'item 2', 'item 3', 'item 4', 'item 5'], + }, + { text: '\n\nOrdered list - type: lower-roman', style: 'header' }, + { + type: 'lower-roman', + ol: ['item 1', 'item 2', 'item 3', 'item 4', 'item 5'], + }, + { text: '\n\nOrdered list - type: none', style: 'header' }, + { + type: 'none', + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nUnordered list - type: none', style: 'header' }, + { + type: 'none', + ul: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list with own separator', style: 'header' }, + { + separator: ')', + ol: ['item 1', 'item 2', 'item 3'], + }, + { + text: '\n\nOrdered list with own complex separator', + style: 'header', + }, + { + separator: ['(', ')'], + ol: ['item 1', 'item 2', 'item 3'], + }, + { text: '\n\nOrdered list with own items type', style: 'header' }, + { + ol: [ + 'item 1', + { text: 'item 2', listType: 'none' }, + { text: 'item 3', listType: 'upper-roman' }, + ], + }, + { text: '\n\nUnordered list with own items type', style: 'header' }, + { + ul: [ + 'item 1', + { text: 'item 2', listType: 'none' }, + { text: 'item 3', listType: 'circle' }, + ], + }, + ], + styles: { + header: { + bold: true, + fontSize: 15, + }, + }, + defaultStyle: { + fontSize: 12, + }, +}; + +const margins: TDocumentDefinitions = { + content: [ + { + stack: [ + 'This header has both top and bottom margins defined', + { text: 'This is a subheader', style: 'subheader' }, + ], + style: 'header', + }, + { + text: [ + "Margins have slightly different behavior than other layout properties. They are not inherited, unlike anything else. They're applied only to those nodes which explicitly ", + 'set margin or style property.\n', + ], + }, + { + text: 'This paragraph (consisting of a single line) directly sets top and bottom margin to 20', + margin: [0, 20], + }, + { + stack: [ + { + text: [ + 'This line begins a stack of paragraphs. The whole stack uses a ', + { text: 'superMargin', italics: true }, + ' style (with margin and fontSize properties).', + ], + }, + { + text: [ + 'When you look at the', + { text: ' document definition', italics: true }, + ', you will notice that fontSize is inherited by all paragraphs inside the stack.', + ], + }, + 'Margin however is only applied once (to the whole stack).', + ], + style: 'superMargin', + }, + { + stack: [ + // tslint:disable-next-line: max-line-length + "I'm not sure yet if this is the desired behavior. I find it a better approach however. One thing to be considered in the future is an explicit layout property called inheritMargin which could opt-in the inheritance.\n\n", + { + fontSize: 15, + text: [ + 'Currently margins for ', + /* the following margin definition doesn't change anything */ + { text: 'inlines', margin: 20 }, + ' are ignored\n\n', + ], + }, + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + // tslint:disable-next-line: max-line-length + 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Malit profecta versatur nomine ocurreret multavit, officiis viveremus aeternum superstitio suspicor alia nostram, quando nostros congressus susceperant concederetur leguntur iam, vigiliae democritea tantopere causae, atilii plerumque ipsas potitur pertineant multis rem quaeri pro, legendum didicisse credere ex maluisset per videtis. Cur discordans praetereat aliae ruinae dirigentur orestem eodem, praetermittenda divinum. Collegisti, deteriora malint loquuntur officii cotidie finitas referri doleamus ambigua acute. Adhaesiones ratione beate arbitraretur detractis perdiscere, constituant hostis polyaeno. Diu concederetur.\n', + ], + margin: [0, 20, 0, 0], + alignment: 'justify', + }, + ], + styles: { + header: { + fontSize: 18, + bold: true, + alignment: 'right', + margin: [0, 190, 0, 80], + }, + subheader: { + fontSize: 14, + }, + superMargin: { + margin: [20, 0, 40, 0], + fontSize: 15, + }, + }, +}; + +const images: TDocumentDefinitions = { + content: [ + "pdfmake (since it's based on pdfkit) supports JPEG and PNG format", + 'If no width/height/fit is provided, image original size will be used', + { + image: 'examples/fonts/sampleImage.jpg', + }, + 'If you specify width, image will scale proportionally', + { + image: 'examples/fonts/sampleImage.jpg', + width: 150, + }, + 'If you specify both width and height - image will be stretched', + { + image: 'examples/fonts/sampleImage.jpg', + width: 150, + height: 150, + }, + 'You can also fit the image inside a rectangle', + { + image: 'examples/fonts/sampleImage.jpg', + fit: [100, 100], + pageBreak: 'after', + }, + + 'Images can be also provided in dataURL format...', + { + image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAACklEQVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg==', + width: 200, + }, + 'or be declared in an "images" dictionary and referenced by name', + { + image: 'building', + width: 200, + }, + ], + images: { + building: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAACklEQVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg==', + }, +}; + +const svgs: TDocumentDefinitions = { + content: [ + 'SVG nodes behave similar to images by supporting width/height or fit', + 'It is however not yet possible to use svg files or to have a library of svgs in the document definition', + '\n', + 'Note that before you can use SVG nodes you must install svg-to-pdfkit as it is not included with pdfmake to keep bundle size down', + { + svg: '', + width: 450, + height: 400, + }, + 'If you specify width, svg will scale proportionally', + { + svg: '', + width: 200, + }, + 'You can also fit the svg inside a rectangle', + { + svg: '', + fit: [100, 100], + }, + ], +}; diff --git a/types/pdfmake/tsconfig.json b/types/pdfmake/tsconfig.json index 2e8b5b10af..2cf7d95a3f 100644 --- a/types/pdfmake/tsconfig.json +++ b/types/pdfmake/tsconfig.json @@ -19,6 +19,12 @@ }, "files": [ "index.d.ts", - "pdfmake-tests.ts" + "test/pdfmake-interfaces-tests.ts", + "test/pdfmake-playground-examples-tests.ts", + "test/pdfmake-examples-tests.ts", + "test/pdfmake-global-tests.ts", + "test/pdfmake-import-default-tests.ts", + "test/pdfmake-module-browser-tests.ts", + "test/pdfmake-module-server-tests.ts" ] }