Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V3.0.0 #56

Merged
merged 10 commits into from
Jan 26, 2021
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
4 changes: 2 additions & 2 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: windows-latest
strategy:
matrix:
node-version: ['10.x', '11.x', '12.x', '13.x']
node-version: ['10.x', '11.x', '12.x']
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
Expand Down Expand Up @@ -49,7 +49,7 @@ jobs:
runs-on: windows-latest
strategy:
matrix:
node-version: ['13.x']
node-version: ['12.14.1']
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
Expand Down
66 changes: 31 additions & 35 deletions API.md
Original file line number Diff line number Diff line change
@@ -1,102 +1,98 @@
<a name="CanvasRenderService"></a>
<a name="ChartJSNodeCanvas"></a>

## CanvasRenderService
## ChartJSNodeCanvas
**Kind**: global class

* [CanvasRenderService](#CanvasRenderService)
* [new CanvasRenderService(width, height, chartCallback, type, chartJsFactory)](#new_CanvasRenderService_new)
* [.renderToDataURL(configuration, mimeType)](#CanvasRenderService+renderToDataURL)
* [.renderToDataURLSync(configuration, mimeType)](#CanvasRenderService+renderToDataURLSync)
* [.renderToBuffer(configuration, mimeType)](#CanvasRenderService+renderToBuffer)
* [.renderToBufferSync(configuration, mimeType)](#CanvasRenderService+renderToBufferSync)
* [.renderToStream(configuration, mimeType)](#CanvasRenderService+renderToStream)
* [.registerFont(path, options)](#CanvasRenderService+registerFont)
* [ChartJSNodeCanvas](#ChartJSNodeCanvas)
* [new ChartJSNodeCanvas(options)](#new_ChartJSNodeCanvas_new)
* [.renderToDataURL(configuration, mimeType)](#ChartJSNodeCanvas+renderToDataURL)
* [.renderToDataURLSync(configuration, mimeType)](#ChartJSNodeCanvas+renderToDataURLSync)
* [.renderToBuffer(configuration, mimeType)](#ChartJSNodeCanvas+renderToBuffer)
* [.renderToBufferSync(configuration, mimeType)](#ChartJSNodeCanvas+renderToBufferSync)
* [.renderToStream(configuration, mimeType)](#ChartJSNodeCanvas+renderToStream)
* [.registerFont(path, options)](#ChartJSNodeCanvas+registerFont)

<a name="new_CanvasRenderService_new"></a>
<a name="new_ChartJSNodeCanvas_new"></a>

### new CanvasRenderService(width, height, chartCallback, type, chartJsFactory)
### new ChartJSNodeCanvas(options)
Create a new instance of CanvasRenderService.


| Param | Description |
| --- | --- |
| width | The width of the charts to render, in pixels. |
| height | The height of the charts to render, in pixels. |
| chartCallback | optional callback which is called once with a new ChartJS global reference as the only parameter. |
| type | optional The canvas type ('PDF' or 'SVG'), see the [canvas pdf doc](https://github.com/Automattic/node-canvas#pdf-output-support). |
| chartJsFactory | optional provider for chart.js. |
| options | Configuration for this instance |

<a name="CanvasRenderService+renderToDataURL"></a>
<a name="ChartJSNodeCanvas+renderToDataURL"></a>

### canvasRenderService.renderToDataURL(configuration, mimeType)
### chartJSNodeCanvas.renderToDataURL(configuration, mimeType)
Render to a data url.

**Kind**: instance method of [<code>CanvasRenderService</code>](#CanvasRenderService)
**Kind**: instance method of [<code>ChartJSNodeCanvas</code>](#ChartJSNodeCanvas)
**See**: https://github.com/Automattic/node-canvas#canvastodataurl

| Param | Default | Description |
| --- | --- | --- |
| configuration | | The Chart JS configuration for the chart to render. |
| mimeType | <code>image/png</code> | The image format, `image/png` or `image/jpeg`. |

<a name="CanvasRenderService+renderToDataURLSync"></a>
<a name="ChartJSNodeCanvas+renderToDataURLSync"></a>

### canvasRenderService.renderToDataURLSync(configuration, mimeType)
### chartJSNodeCanvas.renderToDataURLSync(configuration, mimeType)
Render to a data url synchronously.

**Kind**: instance method of [<code>CanvasRenderService</code>](#CanvasRenderService)
**Kind**: instance method of [<code>ChartJSNodeCanvas</code>](#ChartJSNodeCanvas)
**See**: https://github.com/Automattic/node-canvas#canvastodataurl

| Param | Default | Description |
| --- | --- | --- |
| configuration | | The Chart JS configuration for the chart to render. |
| mimeType | <code>image/png</code> | The image format, `image/png` or `image/jpeg`. |

<a name="CanvasRenderService+renderToBuffer"></a>
<a name="ChartJSNodeCanvas+renderToBuffer"></a>

### canvasRenderService.renderToBuffer(configuration, mimeType)
### chartJSNodeCanvas.renderToBuffer(configuration, mimeType)
Render to a buffer.

**Kind**: instance method of [<code>CanvasRenderService</code>](#CanvasRenderService)
**Kind**: instance method of [<code>ChartJSNodeCanvas</code>](#ChartJSNodeCanvas)
**See**: https://github.com/Automattic/node-canvas#canvastobuffer

| Param | Default | Description |
| --- | --- | --- |
| configuration | | The Chart JS configuration for the chart to render. |
| mimeType | <code>image/png</code> | A string indicating the image format. Valid options are `image/png`, `image/jpeg` (if node-canvas was built with JPEG support) or `raw` (unencoded ARGB32 data in native-endian byte order, top-to-bottom). Defaults to `image/png` for image canvases, or the corresponding type for PDF or SVG canvas. |

<a name="CanvasRenderService+renderToBufferSync"></a>
<a name="ChartJSNodeCanvas+renderToBufferSync"></a>

### canvasRenderService.renderToBufferSync(configuration, mimeType)
### chartJSNodeCanvas.renderToBufferSync(configuration, mimeType)
Render to a buffer synchronously.

**Kind**: instance method of [<code>CanvasRenderService</code>](#CanvasRenderService)
**Kind**: instance method of [<code>ChartJSNodeCanvas</code>](#ChartJSNodeCanvas)
**See**: https://github.com/Automattic/node-canvas#canvastobuffer

| Param | Default | Description |
| --- | --- | --- |
| configuration | | The Chart JS configuration for the chart to render. |
| mimeType | <code>image/png</code> | A string indicating the image format. Valid options are `image/png`, `image/jpeg` (if node-canvas was built with JPEG support), `raw` (unencoded ARGB32 data in native-endian byte order, top-to-bottom), `application/pdf` (for PDF canvases) and image/svg+xml (for SVG canvases). Defaults to `image/png` for image canvases, or the corresponding type for PDF or SVG canvas. |

<a name="CanvasRenderService+renderToStream"></a>
<a name="ChartJSNodeCanvas+renderToStream"></a>

### canvasRenderService.renderToStream(configuration, mimeType)
### chartJSNodeCanvas.renderToStream(configuration, mimeType)
Render to a stream.

**Kind**: instance method of [<code>CanvasRenderService</code>](#CanvasRenderService)
**Kind**: instance method of [<code>ChartJSNodeCanvas</code>](#ChartJSNodeCanvas)
**See**: https://github.com/Automattic/node-canvas#canvascreatepngstream

| Param | Default | Description |
| --- | --- | --- |
| configuration | | The Chart JS configuration for the chart to render. |
| mimeType | <code>image/png</code> | A string indicating the image format. Valid options are `image/png`, `image/jpeg` (if node-canvas was built with JPEG support), `application/pdf` (for PDF canvases) and image/svg+xml (for SVG canvases). Defaults to `image/png` for image canvases, or the corresponding type for PDF or SVG canvas. |

<a name="CanvasRenderService+registerFont"></a>
<a name="ChartJSNodeCanvas+registerFont"></a>

### canvasRenderService.registerFont(path, options)
### chartJSNodeCanvas.registerFont(path, options)
Use to register the font with Canvas to use a font file that is not installed as a system font, this must be done before the Canvas is created.

**Kind**: instance method of [<code>CanvasRenderService</code>](#CanvasRenderService)
**Kind**: instance method of [<code>ChartJSNodeCanvas</code>](#ChartJSNodeCanvas)

| Param | Description |
| --- | --- |
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
3.0.0
-----

Rewrote `ChartJSNodeCanvas` API, the constructor and plugins in particular.
103 changes: 51 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ npm i chartjs-node-canvas chart.js

This is limited by the upstream dependency [canvas](https://github.com/Automattic/node-canvas).

See the `package.json` `engines` section for the current supported Node version. This is not limited using `engineStrict` so you can try a new version if you like. You will need to do a `npm rebuild` to rebuild the canvas binaries.
See the GitHub Actions [yml](.github/workflows/nodejs.yml) section for the current supported Node version(s). You will need to do a `npm rebuild` to rebuild the canvas binaries.

## Features

Expand Down Expand Up @@ -78,11 +78,11 @@ See the [API docs](https://github.com/SeanSobey/ChartjsNodeCanvas/blob/master/AP
## Usage

```js
const { CanvasRenderService } = require('chartjs-node-canvas');
const { ChartJSNodeCanvas } = require('chartjs-node-canvas');

const width = 400; //px
const height = 400; //px
const canvasRenderService = new CanvasRenderService(width, height, (ChartJS) => { });
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height });

(async () => {
const configuration = {
Expand All @@ -96,19 +96,17 @@ const canvasRenderService = new CanvasRenderService(width, height, (ChartJS) =>

### Memory Management

Every instance of `CanvasRenderService` creates its own [canvas](https://github.com/Automattic/node-canvas). To ensure efficient memory and GC use make sure your implementation creates as few instances as possible and reuses them:
Every instance of `ChartJSNodeCanvas` creates its own [canvas](https://github.com/Automattic/node-canvas). To ensure efficient memory and GC use make sure your implementation creates as few instances as possible and reuses them:

```js
const { CanvasRenderService } = require('chartjs-node-canvas');

// Re-use one service, or as many as you need for different canvas size requirements
const smallCanvasRenderService = new CanvasRenderService(400, 400);
const bigCanvasRenderService = new CanvasRenderService(2000, 2000);
const smallChartJSNodeCanvas = new ChartJSNodeCanvas({ width: 400, height: 400 });
const bigCChartJSNodeCanvas = new ChartJSNodeCanvas({ width: 2000, height: 2000 });

// Expose just the 'render' methods to downstream code so they don't have to worry about life-cycle management.
exports = {
renderSmallChart: (configuration) => smallCanvasRenderService.renderToBuffer(configuration),
renderBigChart: (configuration) => bigCanvasRenderService.renderToBuffer(configuration)
renderSmallChart: (configuration) => smallChartJSNodeCanvas.renderToBuffer(configuration),
renderBigChart: (configuration) => bigCChartJSNodeCanvas.renderToBuffer(configuration)
};
```

Expand All @@ -117,11 +115,13 @@ exports = {
Just use the ChartJS reference in the callback:

```js
const canvasRenderService = new CanvasRenderService(width, height, (ChartJS) => {
const chartJSNodeCanvas = new ChartJSNodeCanvas({
width, height, chartCallback: (ChartJS) => {
// New chart type example: https://www.chartjs.org/docs/latest/developers/charts.html
ChartJS.controllers.MyType = Chart.DatasetController.extend({
// chart implementation
});
}
});
```

Expand All @@ -130,98 +130,97 @@ const canvasRenderService = new CanvasRenderService(width, height, (ChartJS) =>
Just use the ChartJS reference in the callback:

```js
const canvasRenderService = new CanvasRenderService(width, height, (ChartJS) => {
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height, chartCallback: (ChartJS) => {
// Global config example: https://www.chartjs.org/docs/latest/configuration/
ChartJS.defaults.global.elements.rectangle.borderWidth = 2;
});
} });
```

### Custom Fonts

Just use the `registerFont` method:

```js
const canvasRenderService = new CanvasRenderService(width, height, (ChartJS) => {
const chartJSNodeCanvas = new ChartJSNodeCanvas(width, height, chartCallback: (ChartJS) => {
// Just example usage
ChartJS.defaults.global.defaultFontFamily = 'VTKS UNAMOUR';
});
// Register before rendering any charts
canvasRenderService.registerFont('./testData/VTKS UNAMOUR.ttf', { family: 'VTKS UNAMOUR' });
chartJSNodeCanvas.registerFont('./testData/VTKS UNAMOUR.ttf', { family: 'VTKS UNAMOUR' });
```

See the node-canvas [docs](https://github.com/Automattic/node-canvas#registerfont) and the chart js [docs](https://www.chartjs.org/docs/latest/general/fonts.html).

### Loading plugins

This library is designed to make loading plugins as simple as possible. For legacy plugins, you should just be able to add the module name to the appropriate array option and the library handles the rest.

The Chart.JS [plugin API](https://www.chartjs.org/docs/latest/developers/plugins.html) has changed over time and this requires compatibility options for the different ways plugins have been historically loaded. ChartJS Node Canvas has a `plugin` option with specifiers for the different ways supported plugin loading methods are handled. If you are not sure about your plugin, just try the different ones until your plugin loads:

#### Newer plugins

Just use the ChartJS reference in the callback:
Let `ChartJSNodeCanvas` manage the lifecycle of the plugin itself, each instance will have a separate instance of the plugin:

```js
const canvasRenderService = new CanvasRenderService(width, height, (ChartJS) => {
// Global plugin example: https://www.chartjs.org/docs/latest/developers/plugins.html
ChartJS.plugins.register({
// plugin implementation
});
const chartJSNodeCanvas = new ChartJSNodeCanvas(width, height, plugins: {
modern: ['chartjs-plugin-annotation']
});
```

#### Older plugins
You want to share the plugin instance, this may cause unwanted issues, use at own risk:

The key to getting older plugins working is knowing that this package uses an equivalent to [fresh-require](https://www.npmjs.com/package/fresh-require) by default to retrieve its version of `chart.js`.
```js
const chartJSNodeCanvas = new ChartJSNodeCanvas(width, height, plugins: {
modern: [require('chartjs-plugin-annotation')]
});
```

There are some tools you can use to solve any issues with the way older ChartJS plugins that do not use the newer global plugin registration API, and instead either load chartjs itself or expect a global variable:
#### Older plugins

---

1. Temporary global variable for ChartJs:
1. Plugin that expects a global Chart variable.

```js
const canvasRenderService = new CanvasRenderService(width, height, (ChartJS) => {
global.Chart = ChartJS;
require('<chart plugin>');
delete global.Chart;
const chartJSNodeCanvas = new ChartJSNodeCanvas(width, height, plugins: {
requireChartJSLegacy: ['<some plugin>']
});
```

This should work for any plugin that expects a global Chart variable.

---

1. Chart factory function for `CanvasRenderService`:
1. Plugins that `require` ChartJS themselves.

```js
const chartJsFactory = () => {
const chartJS = require('chart.js');
require('<chart plugin>');
// Clear the require cache so to allow `CanvasRenderService` separate instances of ChartJS and plugins.
delete require.cache[require.resolve('chart.js')];
delete require.cache[require.resolve('chart plugin')];
return chartJS;
};
const canvasRenderService = new CanvasRenderService(width, height, undefined, undefined, chartJsFactory);
const chartJSNodeCanvas = new ChartJSNodeCanvas(width, height, plugins: {
globalVariableLegacy: ['chartjs-plugin-crosshair']
});
```

This will work for plugins that `require` ChartJS themselves.

---

1. Register plugin directly with ChartJS:
3. Register plugin directly with ChartJS:

```js
const freshRequire = require('fresh-require');

const canvasRenderService = new CanvasRenderService(width, height, (ChartJS) => {
// Use 'fresh-require' to allow `CanvasRenderService` separate instances of ChartJS and plugins.
ChartJS.plugins.register(freshRequire('<chart plugin>', require));
const chartJSNodeCanvas = new ChartJSNodeCanvas(width, height, plugins: {
requireLegacy: ['chartjs-plugin-datalabels']
});
```

This will work with plugins that just return a plugin object and do no specific loading themselves.

---

These approaches can be combined also.
These approaches can be combined also:

```js
const chartJSNodeCanvas = new ChartJSNodeCanvas(width, height, plugins: {
modern: ['chartjs-plugin-annotation'],


requireLegacy: ['chartjs-plugin-datalabels']
});
```

See the [tests](src/index.e2e.spec.ts#106) for some examples.

## Full Example

Expand Down
3 changes: 2 additions & 1 deletion dist/freshRequire.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export declare function freshRequire(file: string): any;
/// <reference types="node" />
export declare const freshRequire: NodeRequireFunction;
6 changes: 3 additions & 3 deletions dist/freshRequire.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/freshRequire.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading