Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
"eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }],
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"files.trimTrailingWhitespace": true
"files.trimTrailingWhitespace": true,
"cSpell.words": ["bbox", "pdfmkr"]
}
48 changes: 42 additions & 6 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,82 @@ import eslintJs from '@eslint/js';
import eslintConfigPrettier from 'eslint-config-prettier';
import importPlugin from 'eslint-plugin-import';
import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort';
import globals from 'globals';
import tseslint from 'typescript-eslint';

export default tseslint.config(
{
// global ignores: must be used without any other keys in the config object
ignores: ['node_modules/', 'dist/', 'build/', 'out/', 'coverage/', '*.local', '*~'],
ignores: [
'node_modules/',
'dist/',
'out/',
'build/',
'coverage/',
'examples/',
'**/*.local',
'*~',
'eslint.config.js',
],
},
eslintJs.configs.recommended,
eslintConfigPrettier,
...tseslint.configs.recommended,
...tseslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
{
files: ['**/*.js', '**/*.ts'],
plugins: {
import: importPlugin,
'simple-import-sort': simpleImportSortPlugin,
},
languageOptions: {
ecmaVersion: 2022,
ecmaVersion: 2024,
sourceType: 'module',
globals: {
...globals.node,
...globals.browser,
},
},
rules: {
eqeqeq: ['error', 'always', { null: 'ignore' }],
'no-console': ['error', { allow: ['warn', 'error'] }],
'no-constant-condition': ['error', { checkLoops: false }],
'one-var': ['error', 'never'],
'object-shorthand': ['error', 'always'],
'prefer-const': ['error', { destructuring: 'all' }],
'require-await': 'error',
'no-useless-escape': 'error',
'no-unneeded-ternary': 'error',
'no-unused-expressions': 'error',
'no-multi-assign': 'error',
'no-throw-literal': 'error',
'no-param-reassign': 'error',
'no-else-return': ['error', { allowElseIf: false }],
'dot-notation': 'error',
'one-var': ['error', 'never'],
'require-await': 'error',

'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'@typescript-eslint/consistent-type-imports': ['error', { fixStyle: 'inline-type-imports' }],
'@typescript-eslint/parameter-properties': 'error',
'@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }],

// TODO: revisit when we got rid of pdf-lib internals
'@typescript-eslint/no-unsafe-assignment': ['off'],
'@typescript-eslint/no-unsafe-call': ['off'],
'@typescript-eslint/no-unsafe-member-access': ['off'],
'@typescript-eslint/no-unsafe-return': ['off'],

'simple-import-sort/imports': 'error',
'import/extensions': ['error', 'ignorePackages', { js: 'never', ts: 'always' }],
'import/no-default-export': 'error',
'import/no-duplicates': 'error',
'import/extensions': ['error', 'ignorePackages', { ts: 'always' }],
},
},
);
6 changes: 1 addition & 5 deletions examples/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
package-lock.json
yarn.lock
deno.lock
bun.lockb
fonts/
*.pdf
out/
42 changes: 4 additions & 38 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,54 +1,20 @@
# Running the examples

## Prerequisites

- A recent version of [Node], [Bun], or [Deno].

## Download fonts

Fonts are not included in the repository, but can be downloaded using
the `download-fonts.sh` script. This places the downloaded fonts in the
`fonts` directory.

```sh
$ ./download-fonts.sh
```

## Install dependencies

In the examples directory, use your favorite installer to install the
`pdfmkr` dependency.

```sh
$ cd examples
$ npm install
# OR
$ yarn install
# OR
$ bun install
cd examples
./download-fonts.sh
```

If you're using [Deno], you can skip this step.

## Run the examples

```sh
$ node src/hello-world.js
# OR
$ bun run src/hello-world.js
# OR
$ deno run --allow-read --allow-write src/hello-world.js
```

### Pro-tip: watch mode

While experimenting with the examples, you can use the `--watch` flag to
automatically re-create a PDF when the file changes, e.g.:

```sh
$ bun run --watch src/hello-world.js
node examples/hello-world.ts
```

[Node]: https://nodejs.org/en/
[Bun]: https://bun.sh/
[Deno]: https://deno.land/
Generated PDFs are written to `examples/out/`.
26 changes: 18 additions & 8 deletions examples/src/anchors.js → examples/anchors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { readFile, writeFile } from 'node:fs/promises';
/* eslint-disable no-console */
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';

import { columns, PdfMaker, rows, text } from 'pdfmkr';
import type { DocumentDefinition } from '../src/index.ts';
import { columns, PdfMaker, rows, text } from '../src/index.ts';

const exampleDir = fileURLToPath(new URL('.', import.meta.url));
const outDir = join(exampleDir, 'out');

const loremIpsum =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor' +
Expand All @@ -10,7 +17,7 @@ const loremIpsum =
' Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt ' +
'mollit anim id est laborum.';

const def = {
const def: DocumentDefinition = {
margin: { x: '20mm', y: '0.5cm' },
defaultStyle: {
fontSize: 12,
Expand Down Expand Up @@ -50,15 +57,18 @@ const def = {
],
};

function range(n) {
function range(n: number) {
return [...Array(n).keys()];
}

const pdfMaker = new PdfMaker();

pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed.ttf'));
pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed-Bold.ttf'));
pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed-Oblique.ttf'));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed.ttf')));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed-Bold.ttf')));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed-Oblique.ttf')));

const pdf = await pdfMaker.makePdf(def);
await writeFile('./out/anchors.pdf', pdf);
await mkdir(outDir, { recursive: true });
const outFile = join(outDir, 'anchors.pdf');
await writeFile(outFile, pdf);
console.log(`PDF written to ${outFile}`);
21 changes: 15 additions & 6 deletions examples/src/graphics.js → examples/graphics.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { readFile, writeFile } from 'node:fs/promises';
/* eslint-disable no-console */
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';

import { circle, line, path, PdfMaker, rect, text } from 'pdfmkr';
import { circle, line, path, PdfMaker, rect, text } from '../src/index.ts';

const exampleDir = fileURLToPath(new URL('.', import.meta.url));
const outDir = join(exampleDir, 'out');

const document = {
defaultStyle: {
Expand Down Expand Up @@ -143,9 +149,12 @@ const document = {

const pdfMaker = new PdfMaker();

pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed.ttf'));
pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed-Bold.ttf'));
pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed-Oblique.ttf'));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed.ttf')));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed-Bold.ttf')));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed-Oblique.ttf')));

const pdf = await pdfMaker.makePdf(document);
await writeFile('./out/graphics.pdf', pdf);
await mkdir(outDir, { recursive: true });
const outFile = join(outDir, 'graphics.pdf');
await writeFile(outFile, pdf);
console.log(`PDF written to ${outFile}`);
22 changes: 16 additions & 6 deletions examples/src/guides.js → examples/guides.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { readFile, writeFile } from 'node:fs/promises';
/* eslint-disable no-console */
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';

import { columns, PdfMaker, text } from 'pdfmkr';
import type { DocumentDefinition } from '../src/index.ts';
import { columns, PdfMaker, text } from '../src/index.ts';

const document = {
const exampleDir = fileURLToPath(new URL('.', import.meta.url));
const outDir = join(exampleDir, 'out');

const document: DocumentDefinition = {
// Enable guides to render indicators for blocks, paddings, and margins
dev: { guides: true },
defaultStyle: {
Expand Down Expand Up @@ -83,8 +90,11 @@ const document = {
};

const pdfMaker = new PdfMaker();
pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed.ttf'));
pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed-Bold.ttf'));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed.ttf')));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed-Bold.ttf')));

const pdf = await pdfMaker.makePdf(document);
await writeFile('./out/guides.pdf', pdf);
await mkdir(outDir, { recursive: true });
const outFile = join(outDir, 'guides.pdf');
await writeFile(outFile, pdf);
console.log(`PDF written to ${outFile}`);
29 changes: 29 additions & 0 deletions examples/hello-world.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* eslint-disable no-console */
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';

import { PdfMaker, text } from '../src/index.ts';

const exampleDir = fileURLToPath(new URL('.', import.meta.url));
const outDir = join(exampleDir, 'out');

// The PDF definition
const document = {
// The content is an array of blocks
content: [
// A single text block
text('Hello world!', { fontSize: 24 }),
],
};

// Generate a PDF from the definition
const pdfMaker = new PdfMaker();
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed.ttf')));
const pdf = await pdfMaker.makePdf(document);

// Write the PDF to a file
await mkdir(outDir, { recursive: true });
const outFile = join(outDir, 'hello-world.pdf');
await writeFile(outFile, pdf);
console.log(`PDF written to ${outFile}`);
25 changes: 17 additions & 8 deletions examples/src/images.js → examples/images.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { readFile, writeFile } from 'node:fs/promises';
/* eslint-disable no-console */
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';

import { columns, image, PdfMaker, rect, rows, text } from 'pdfmkr';
import { columns, image, PdfMaker, rect, rows, text } from '../src/index.ts';

const exampleDir = fileURLToPath(new URL('.', import.meta.url));
const outDir = join(exampleDir, 'out');

// Draw a frame around a block
const drawFrame = ({ width, height }) => [
const drawFrame = ({ width, height }: { width: number; height: number }) => [
rect(0, 0, width, height, { lineColor: 'gray', lineDash: [2] }),
];

Expand Down Expand Up @@ -56,11 +62,14 @@ const document = {
};

const pdfMaker = new PdfMaker();
pdfMaker.setResourceRoot('.');
pdfMaker.setResourceRoot(exampleDir);

pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed.ttf'));
pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed-Bold.ttf'));
pdfMaker.registerFont(await readFile('./fonts/DejaVuSansCondensed-Oblique.ttf'));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed.ttf')));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed-Bold.ttf')));
pdfMaker.registerFont(await readFile(join(exampleDir, 'fonts/DejaVuSansCondensed-Oblique.ttf')));

const pdf = await pdfMaker.makePdf(document);
await writeFile('./out/images.pdf', pdf);
await mkdir(outDir, { recursive: true });
const outFile = join(outDir, 'images.pdf');
await writeFile(outFile, pdf);
console.log(`PDF written to ${outFile}`);
16 changes: 16 additions & 0 deletions examples/images/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Sample Image Licenses

This project includes the following sample images.
These images have been resized from their original versions.

## liberty.jpg

Author: George Hodan
Source: https://www.publicdomainpictures.net/en/view-image.php?image=167212&picture=statue-of-liberty
License: CC0 Public Domain, https://creativecommons.org/publicdomain/zero/1.0/

## torus.png

Author: Lucas Vieira
Source: https://commons.wikimedia.org/wiki/File:Blue-torus.png
License: public domain
8 changes: 0 additions & 8 deletions examples/package.json

This file was deleted.

16 changes: 16 additions & 0 deletions examples/run-all-examples.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash
set -e

cd "$(dirname "$0")"

if [ ! -d "fonts" ]; then
echo "Fonts not found. Run ./download-fonts.sh first."
exit 1
fi

for file in *.ts; do
echo "Running $file..."
node "$file"
done

echo "All examples completed."
Loading