Skip to content
Open
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: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,6 @@ build/Release
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules


# Yarn Berry local state
.yarn/
6 changes: 6 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
approvedGitRepositories:
- "**"

enableScripts: true

nodeLinker: node-modules
28 changes: 21 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ QuickChart for Javascript
[![npm](https://img.shields.io/npm/dt/quickchart-js)](https://www.npmjs.com/package/quickchart-js)
[![Build Status](https://travis-ci.com/typpo/quickchart-js.svg?branch=master)](https://travis-ci.com/typpo/quickchart-js)

This is a Javascript client for [quickchart.io](https://quickchart.io), a web service for generating static charts. View the main QuickChart repository [here](https://github.com/typpo/quickchart).
This is a modern Javascript client for [quickchart.io](https://quickchart.io), a web service for generating static charts. View the main QuickChart repository [here](https://github.com/typpo/quickchart).

# Installation

Expand All @@ -22,6 +22,7 @@ This library provides a **QuickChart** object. Import it, instantiate it, and s
const QuickChart = require('quickchart-js');

const myChart = new QuickChart();
// Defaults to Chart.js v4. Use .setVersion('2') for legacy Chart.js v2 configs.
myChart.setConfig({
type: 'bar',
data: { labels: ['Hello world', 'Foo bar'], datasets: [{ label: 'Foo', data: [1, 2] }] },
Expand All @@ -32,7 +33,7 @@ Use `getUrl()` on your quickchart object to get the encoded URL that renders you

```js
console.log(myChart.getUrl());
// Prints: https://quickchart.io/chart?c=%7Btype%3A%27bar%27%2Cdata%3A%7Blabels%3A%5B%27Hello+world%27%2C%27Foo+bar%27%5D%2Cdatasets%3A%5B%7Blabel%3A%27Foo%27%2Cdata%3A%5B1%2C2%5D%7D%5D%7D%7D&w=500&h=300&bkg=transparent&f=png
// Prints: https://quickchart.io/chart?c=%7Btype%3A%27bar%27%2Cdata%3A%7Blabels%3A%5B%27Hello+world%27%2C%27Foo+bar%27%5D%2Cdatasets%3A%5B%7Blabel%3A%27Foo%27%2Cdata%3A%5B1%2C2%5D%7D%5D%7D%7D&w=500&h=300&bkg=%23ffffff&f=png&v=4
```

If you have a large or complicated chart, use `getShortUrl()` on your quickchart object to get a fixed-length URL using the quickchart.io web service:
Expand All @@ -44,12 +45,12 @@ console.log(url);

Or write it to disk:
```js
myChart.toFile('/tmp/mychart.png');
await myChart.toFile('/tmp/mychart.png');
```

The URLs produce this chart image:

<img src="https://quickchart.io/chart?c=%7Btype%3A%27bar%27%2Cdata%3A%7Blabels%3A%5B%27Hello+world%27%2C%27Foo+bar%27%5D%2Cdatasets%3A%5B%7Blabel%3A%27Foo%27%2Cdata%3A%5B1%2C2%5D%7D%5D%7D%7D&w=500&h=300&bkg=transparent&f=png" width=500 />
<img src="https://quickchart.io/chart?c=%7Btype%3A%27bar%27%2Cdata%3A%7Blabels%3A%5B%27Hello+world%27%2C%27Foo+bar%27%5D%2Cdatasets%3A%5B%7Blabel%3A%27Foo%27%2Cdata%3A%5B1%2C2%5D%7D%5D%7D%7D&w=500&h=300&bkg=%23ffffff&f=png&v=4" width=500 />

## Creating a QuickChart object

Expand All @@ -65,6 +66,19 @@ To use the free (community) version, leave it blank:
const qc = new QuickChart();
```

You can also pass options at construction time:

```js
const qc = new QuickChart({
apiKey,
accountId,
width: 800,
height: 400,
version: '4',
format: 'webp',
});
```

## Customizing your chart

### setConfig(chart: Object | string)
Expand All @@ -81,7 +95,7 @@ Sets the height of the chart in pixels. Defaults to 300.

### setFormat(format: string)

Sets the format of the chart. Defaults to `png`. `svg` is also valid.
Sets the format of the chart. Defaults to `png`. Common values include `png`, `webp`, `jpg`, `svg`, and `pdf`.

### setBackgroundColor(color: string)

Expand All @@ -93,7 +107,7 @@ Sets the device pixel ratio of the chart. This will multiply the number of pixe

### setVersion(version: string)

Sets the Chart.js version to use (e.g. `2.9.4` or `3.4.0`). Valid options are shown in the [documentation](https://quickchart.io/documentation/#parameters).
Sets the Chart.js version to use. Defaults to `4` for modern Chart.js configs. Set this to `2`, `2.9.4`, or another supported version when rendering legacy configs. Valid options are shown in the [documentation](https://quickchart.io/documentation/usage/parameters/#version).

### setHost(host: string)

Expand Down Expand Up @@ -147,7 +161,7 @@ qc.setConfig({
qc.setWidth(500).setHeight(300).setBackgroundColor('transparent');

console.log(qc.getUrl());
// https://quickchart.io/chart?c=%7Btype%3A%27bar%27%2Cdata%3A%7Blabels%3A%5B%27Hello+world%27%2C%27Foo+bar%27%5D%2Cdatasets%3A%5B%7Blabel%3A%27Foo%27%2Cdata%3A%5B1%2C2%5D%7D%5D%7D%7D&w=500&h=300&bkg=transparent&f=png
// https://quickchart.io/chart?c=%7Btype%3A%27bar%27%2Cdata%3A%7Blabels%3A%5B%27Hello+world%27%2C%27Foo+bar%27%5D%2Cdatasets%3A%5B%7Blabel%3A%27Foo%27%2Cdata%3A%5B1%2C2%5D%7D%5D%7D%7D&w=500&h=300&bkg=transparent&f=png&v=4
```

Here's a more complicated chart that includes some Javascript:
Expand Down
22 changes: 16 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "quickchart-js",
"version": "3.1.3",
"version": "3.2.0",
"description": "Javascript client for QuickChart.io",
"main": "build/quickchart.cjs.js",
"module": "build/quickchart.mjs",
Expand All @@ -21,10 +21,10 @@
"test": "jest --testPathIgnorePatterns=examples/",
"format": "prettier --single-quote --trailing-comma all --print-width 100 --write \"**/*.{js,ts}\"",
"build": "tsc && yarn build:browser && yarn build:esm && yarn build:cjs",
"build:browser": "esbuild src/index.ts --bundle --sourcemap --external:fs --external:crypto --target=es2015 --global-name=QuickChart --tsconfig=tsconfig.json --footer:js=\"QuickChart = QuickChart.default\" --outfile=build/quickchart.js",
"build:cjs": "esbuild src/index.ts --format=cjs --sourcemap --tree-shaking=true --platform=node --target=node10.4 --global-name=QuickChart --tsconfig=tsconfig.json --footer:js=\"module.exports = module.exports.default;\" --outfile=build/quickchart.cjs.js",
"build:esm": "esbuild src/index.ts --sourcemap --tree-shaking=true --platform=node --target=node10.4 --global-name=QuickChart --tsconfig=tsconfig.json --format=esm --outfile=build/quickchart.mjs",
"build:watch": "esbuild src/index.ts --watch --sourcemap --tree-shaking=true --platform=node --target=node10.4 --global-name=QuickChart --tsconfig=tsconfig.json --footer:js=\"module.exports = module.exports.default;\" --outfile=build/quickchart.cjs.js",
"build:browser": "esbuild src/index.ts --bundle --sourcemap --external:fs --external:crypto --external:node:fs/promises --target=es2020 --global-name=QuickChart --tsconfig=tsconfig.json --footer:js=\"QuickChart = QuickChart.default\" --outfile=build/quickchart.js",
"build:cjs": "esbuild src/index.ts --format=cjs --sourcemap --tree-shaking=true --platform=node --target=node18 --global-name=QuickChart --tsconfig=tsconfig.json --footer:js=\"module.exports = module.exports.default;\" --outfile=build/quickchart.cjs.js",
"build:esm": "esbuild src/index.ts --sourcemap --tree-shaking=true --platform=node --target=node18 --global-name=QuickChart --tsconfig=tsconfig.json --format=esm --outfile=build/quickchart.mjs",
"build:watch": "esbuild src/index.ts --watch --sourcemap --tree-shaking=true --platform=node --target=node18 --global-name=QuickChart --tsconfig=tsconfig.json --footer:js=\"module.exports = module.exports.default;\" --outfile=build/quickchart.cjs.js",
"prepublishOnly": "yarn build",
"publish": "yarn publish"
},
Expand Down Expand Up @@ -52,5 +52,15 @@
"setupFiles": [
"./test/setupJest.js"
]
}
},
"packageManager": "yarn@4.14.1",
"engines": {
"node": ">=18"
},
"files": [
"build",
"src",
"README.md",
"LICENSE"
]
}
68 changes: 45 additions & 23 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,47 @@ import type { Response } from 'cross-fetch';

const SPECIAL_FUNCTION_REGEX: RegExp = /['"]__BEGINFUNCTION__(.*?)__ENDFUNCTION__['"]/g;

const USER_AGENT = `quickchart-js/3.1.0`;
const USER_AGENT = 'quickchart-js/3.2.0';

interface PostData {
export type ChartConfig = ChartConfiguration | Record<string, unknown>;

export interface PostData {
chart: string;
width?: number;
height?: number;
format?: string;
format?: ImageFormat;
version?: string;
backgroundColor?: string;
devicePixelRatio?: number;
key?: string;
}

interface GradientFillOption {
export type ImageFormat = 'png' | 'webp' | 'jpg' | 'jpeg' | 'svg' | 'pdf' | 'base64' | string;

export interface QuickChartOptions {
apiKey?: string;
accountId?: string;
host?: string;
scheme?: 'http' | 'https' | string;
width?: number;
height?: number;
devicePixelRatio?: number;
backgroundColor?: string;
format?: ImageFormat;
version?: string;
}

export interface GradientFillOption {
offset: number;
color: string;
}

interface GradientDimensionOption {
export interface GradientDimensionOption {
width?: number;
height?: number;
}

function doStringify(chartConfig: ChartConfiguration): string | undefined {
function doStringify(chartConfig: ChartConfig): string | undefined {
const str = stringify(chartConfig);
if (!str) {
return undefined;
Expand All @@ -57,30 +74,35 @@ class QuickChart {
private height: number;
private devicePixelRatio: number;
private backgroundColor: string;
private format: string;
private format: ImageFormat;
private version: string;

private chart?: string;
private apiKey?: string;
private accountId?: string;

constructor(apiKey?: string, accountId?: string) {
this.apiKey = apiKey;
this.accountId = accountId;
constructor(apiKeyOrOptions?: string | QuickChartOptions, accountId?: string) {
const options =
typeof apiKeyOrOptions === 'object' && apiKeyOrOptions !== null
? apiKeyOrOptions
: { apiKey: apiKeyOrOptions, accountId };

this.apiKey = options.apiKey;
this.accountId = options.accountId;

this.host = 'quickchart.io';
this.scheme = 'https';
this.host = options.host ?? 'quickchart.io';
this.scheme = options.scheme ?? 'https';

this.chart = undefined;
this.width = 500;
this.height = 300;
this.devicePixelRatio = 1.0;
this.backgroundColor = '#ffffff';
this.format = 'png';
this.version = '2.9.4';
this.width = options.width ?? 500;
this.height = options.height ?? 300;
this.devicePixelRatio = options.devicePixelRatio ?? 1.0;
this.backgroundColor = options.backgroundColor ?? '#ffffff';
this.format = options.format ?? 'png';
this.version = options.version ?? '4';
}

setConfig(chartConfig: string | ChartConfiguration): QuickChart {
setConfig(chartConfig: string | ChartConfig): QuickChart {
this.chart = typeof chartConfig === 'string' ? chartConfig : doStringify(chartConfig);
return this;
}
Expand Down Expand Up @@ -115,7 +137,7 @@ class QuickChart {
return this;
}

setFormat(fmt: string): QuickChart {
setFormat(fmt: ImageFormat): QuickChart {
this.format = fmt;
return this;
}
Expand Down Expand Up @@ -186,7 +208,7 @@ class QuickChart {

getPostData(): PostData {
if (!this.isValid()) {
throw new Error('You must call setConfig creating post data');
throw new Error('You must call setConfig before creating post data');
}

const { width, height, chart, format, version, backgroundColor, devicePixelRatio, apiKey } =
Expand Down Expand Up @@ -260,9 +282,9 @@ class QuickChart {
}

async toFile(pathOrDescriptor: PathLike | FileHandle): Promise<void> {
const fs = require('fs');
const { writeFile } = await import('fs/promises');
const buf = await this.toBinary();
fs.writeFileSync(pathOrDescriptor, buf);
await writeFile(pathOrDescriptor, buf);
}

static getGradientFillHelper(
Expand Down
22 changes: 22 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,28 @@ test('basic chart, no auth', () => {
expect(qc.getUrl()).toContain('/chart?');
expect(qc.getUrl()).toContain('w=500');
expect(qc.getUrl()).toContain('h=300');
expect(qc.getUrl()).toContain('v=4');
});

test('basic chart with constructor options', () => {
const qc = new QuickChart({
host: 'foo.com',
scheme: 'http',
width: 640,
height: 480,
version: '3',
format: 'webp',
});
qc.setConfig({
type: 'bar',
data: { labels: ['Hello world', 'Foo bar'], datasets: [{ label: 'Foo', data: [1, 2] }] },
});

expect(qc.getUrl()).toContain('http://foo.com/chart?');
expect(qc.getUrl()).toContain('w=640');
expect(qc.getUrl()).toContain('h=480');
expect(qc.getUrl()).toContain('v=3');
expect(qc.getUrl()).toContain('f=webp');
});

test('basic chart with custom host', () => {
Expand Down
17 changes: 13 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"compilerOptions": {
"outDir": "build/typescript",
"lib": ["es2015", "dom"],
"lib": [
"ES2021",
"DOM"
],
"declaration": true,
"noUnusedLocals": false,
"noImplicitAny": true,
Expand All @@ -12,7 +15,13 @@
"noImplicitThis": true,
"noImplicitOverride": true,
"alwaysStrict": true,
"esModuleInterop": true
"esModuleInterop": true,
"target": "ES2021",
"moduleResolution": "node",
"skipLibCheck": true,
"module": "ES2020"
},
"include": ["src/**/*"]
}
"include": [
"src/**/*"
]
}
Loading