diff --git a/.editorconfig b/.editorconfig index 8cea3b4f020..922810ad734 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ -# http://editorconfig.org +# https://editorconfig.org root = true [*] @@ -7,7 +7,7 @@ indent_size = 4 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true -insert_final_newline = false +insert_final_newline = true [gulpfile.js] indent_style = space diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index e6ead94ecb3..a926215c1f0 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,42 +1,14 @@ - - - -## Expected Behavior - - - -## Current Behavior - - + Ahoy! -## Possible Solution - - + You're seeing this because you felt none of the other options fit the type of + issue you'd like to create. Please use this opportunity to tell us about the + type of issue you were looking for, so we can try to accommodate similar + issues in the future. -## Steps to Reproduce (for bugs) - - -1. -2. -3. -4. - -## Context - - - -## Environment - -* Chart.js version: -* Browser name and version: -* Link to your project: + If you're using this template to report an issue covered by an existing issue + type, we'll close it as invalid faster than you can spell 'Mississippi'. +--> diff --git a/.github/ISSUE_TEMPLATE/BUG.md b/.github/ISSUE_TEMPLATE/BUG.md new file mode 100644 index 00000000000..1d9ca8c2754 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG.md @@ -0,0 +1,50 @@ +--- +name: Bug Report +about: Something went awry +labels: 'type: bug' +--- + + + +## Expected Behavior + + +## Current Behavior + + +## Possible Solution + + +## Steps to Reproduce (for bugs) + + +## Context + + +## Environment + +* Chart.js version: +* Browser name and version: +* Link to your project: diff --git a/.github/ISSUE_TEMPLATE/DOCS.md b/.github/ISSUE_TEMPLATE/DOCS.md new file mode 100644 index 00000000000..70e8b34c1ef --- /dev/null +++ b/.github/ISSUE_TEMPLATE/DOCS.md @@ -0,0 +1,25 @@ +--- +name: Documentation +about: Are the docs lacking or missing something? +labels: 'type: documentation' +--- + +Documentation Is: + + + +- [ ] Missing or needed +- [ ] Confusing +- [ ] Not Sure? + +### Please Explain in Detail... + + +### Your Proposal for Changes + + +### Example + diff --git a/.github/ISSUE_TEMPLATE/FEATURE.md b/.github/ISSUE_TEMPLATE/FEATURE.md new file mode 100644 index 00000000000..22b716a1db5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/FEATURE.md @@ -0,0 +1,25 @@ +--- +name: Feature Request +about: Suggest an idea +labels: 'type: enhancement' +--- + + + +### Feature Proposal + + +### Feature Use Case + + + +## Possible Implementation + diff --git a/.github/ISSUE_TEMPLATE/SUPPORT.md b/.github/ISSUE_TEMPLATE/SUPPORT.md new file mode 100644 index 00000000000..1b554bbf4bb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/SUPPORT.md @@ -0,0 +1,27 @@ +--- +name: Support, Help, and Advice +about: Need help or support? Head to https://stackoverflow.com/questions/tagged/chart.js +labels: 'type: support' +--- + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9625965b493..7dd68ba0f29 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,8 +4,8 @@ Please consider the following before submitting a pull request: Guidelines for contributing: https://github.com/chartjs/Chart.js/blob/master/docs/developers/contributing.md Example of changes on an interactive website such as the following: -- http://jsbin.com/ -- http://jsfiddle.net/ -- http://codepen.io/pen/ -- Premade template: http://codepen.io/pen?template=JXVYzq +- https://jsbin.com/ +- https://jsfiddle.net/ +- https://codepen.io/pen/ +- Premade template: https://codepen.io/pen?template=JXVYzq --> diff --git a/.gitignore b/.gitignore index 0a65be9b282..f275dac0706 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ /package-lock.json .DS_Store .idea +.project +.settings .vscode bower.json *.log diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 47b4948ed27..00000000000 --- a/.npmignore +++ /dev/null @@ -1,13 +0,0 @@ -/.git -/.github -/coverage -/custom -/dist/*.zip -/docs/index.md -/node_modules - -.codeclimate.yml -.DS_Store -.gitignore -.idea -.travis.yml diff --git a/.travis.yml b/.travis.yml index 9b38ab3c146..0be85778214 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "6" + - lts/* before_install: - "export CHROME_BIN=/usr/bin/google-chrome" @@ -42,13 +42,12 @@ deploy: branch: release - provider: releases api_key: $GITHUB_AUTH_TOKEN - file: - - "./dist/Chart.bundle.js" - - "./dist/Chart.bundle.min.js" - - "./dist/Chart.js" - - "./dist/Chart.min.js" - - "./dist/Chart.js.zip" skip_cleanup: true + file_glob: true + file: + - ./dist/*.css + - ./dist/*.js + - ./dist/*.zip on: tags: true - provider: npm diff --git a/MAINTAINING.md b/MAINTAINING.md index 5e34f433c18..288b03945ff 100644 --- a/MAINTAINING.md +++ b/MAINTAINING.md @@ -5,7 +5,7 @@ Chart.js relies on [Travis CI](https://travis-ci.org/) to automate the library [ ### Releasing a New Version 1. draft release notes on [GitHub](https://github.com/chartjs/Chart.js/releases/new) for the upcoming tag -1. update `master` `package.json` version using [semver](http://semver.org/) semantic +1. update `master` `package.json` version using [semver](https://semver.org/) semantic 1. merge `master` into the `release` branch 1. follow the build process on [Travis CI](https://travis-ci.org/chartjs/Chart.js) diff --git a/README.md b/README.md index d7e966ca784..5a522a5e915 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,32 @@ -# Chart.js - -[![travis](https://img.shields.io/travis/chartjs/Chart.js.svg?style=flat-square&maxAge=60)](https://travis-ci.org/chartjs/Chart.js) [![coveralls](https://img.shields.io/coveralls/chartjs/Chart.js.svg?style=flat-square&maxAge=600)](https://coveralls.io/github/chartjs/Chart.js?branch=master) [![codeclimate](https://img.shields.io/codeclimate/maintainability/chartjs/Chart.js.svg?style=flat-square&maxAge=600)](https://codeclimate.com/github/chartjs/Chart.js) [![slack](https://img.shields.io/badge/slack-chartjs-blue.svg?style=flat-square&maxAge=3600)](https://chartjs-slack.herokuapp.com/) - -*Simple HTML5 Charts using the canvas element* [chartjs.org](http://www.chartjs.org) - -## Installation - -You can download the latest version of Chart.js from the [GitHub releases](https://github.com/chartjs/Chart.js/releases/latest) or use a [Chart.js CDN](https://cdnjs.com/libraries/Chart.js). - -To install via npm: - -```bash -npm install chart.js --save -``` - -To install via bower: -```bash -bower install chart.js --save -``` - -### Selecting the Correct Build - -Chart.js provides two different builds for you to choose: `Stand-Alone Build`, `Bundled Build`. - -#### Stand-Alone Build -Files: -* `dist/Chart.js` -* `dist/Chart.min.js` - -The stand-alone build includes Chart.js as well as the color parsing library. If this version is used, you are required to include [Moment.js](http://momentjs.com/) before Chart.js for the functionality of the time axis. - -#### Bundled Build -Files: -* `dist/Chart.bundle.js` -* `dist/Chart.bundle.min.js` - -The bundled build includes Moment.js in a single file. You should use this version if you require time axes and want to include a single file. You should not use this build if your application already included Moment.js. Otherwise, Moment.js will be included twice which results in increasing page load time and possible version compatibility issues. The Moment.js version in the bundled build is private to Chart.js so if you want to use Moment.js yourself, it's better to use Chart.js (non bundled) and import Moment.js manually. +

+
+ Simple yet flexible JavaScript charting for designers & developers +

+ +

+ Downloads + Builds + Coverage + Awesome + Slack +

## Documentation -You can find documentation at [www.chartjs.org/docs](http://www.chartjs.org/docs). The markdown files that build the site are available under `/docs`. Previous version documentation is available at [www.chartjs.org/docs/latest/developers/#previous-versions](http://www.chartjs.org/docs/latest/developers/#previous-versions). +- [Introduction](https://www.chartjs.org/docs/latest/) +- [Getting Started](https://www.chartjs.org/docs/latest/getting-started/) +- [General](https://www.chartjs.org/docs/latest/general/) +- [Configuration](https://www.chartjs.org/docs/latest/configuration/) +- [Charts](https://www.chartjs.org/docs/latest/charts/) +- [Axes](https://www.chartjs.org/docs/latest/axes/) +- [Developers](https://www.chartjs.org/docs/latest/developers/) +- [Popular Extensions](https://github.com/chartjs/awesome) +- [Samples](https://www.chartjs.org/samples/) ## Contributing -Before submitting an issue or a pull request, please take a moment to look over the [contributing guidelines](https://github.com/chartjs/Chart.js/blob/master/docs/developers/contributing.md) first. For support using Chart.js, please post questions with the [`chartjs` tag on Stack Overflow](http://stackoverflow.com/questions/tagged/chartjs). - -## Building -Instructions on building and testing Chart.js can be found in [the documentation](https://github.com/chartjs/Chart.js/blob/master/docs/developers/contributing.md#building-and-testing). - -## Thanks -- [BrowserStack](https://browserstack.com) for allowing our team to test on thousands of browsers. -- [@n8agrin](https://twitter.com/n8agrin) for the Twitter handle donation. +Instructions on building and testing Chart.js can be found in [the documentation](https://github.com/chartjs/Chart.js/blob/master/docs/developers/contributing.md#building-and-testing). Before submitting an issue or a pull request, please take a moment to look over the [contributing guidelines](https://github.com/chartjs/Chart.js/blob/master/docs/developers/contributing.md) first. For support, please post questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/chartjs) with the `chartjs` tag. ## License -Chart.js is available under the [MIT license](http://opensource.org/licenses/MIT). +Chart.js is available under the [MIT license](https://opensource.org/licenses/MIT). diff --git a/book.json b/book.json index 8b0f73970df..22acbde968c 100644 --- a/book.json +++ b/book.json @@ -3,7 +3,15 @@ "title": "Chart.js documentation", "author": "chartjs", "gitbook": "3.2.2", - "plugins": ["-lunr", "-search", "search-plus", "anchorjs", "chartjs", "ga"], + "plugins": [ + "-lunr", + "-search", + "search-plus", + "anchorjs", + "chartjs", + "ga", + "redirect" + ], "pluginsConfig": { "anchorjs": { "icon": "#", diff --git a/composer.json b/composer.json index 48d05b8dcb7..b332bb0f595 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "chart", "js" ], - "homepage": "http://www.chartjs.org/", + "homepage": "https://www.chartjs.org/", "license": "MIT", "authors": [ { diff --git a/docs/README.md b/docs/README.md index 24ee8d49982..9592ecf2c10 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,21 +4,21 @@ ## Installation -You can download the latest version of Chart.js from the [GitHub releases](https://github.com/chartjs/Chart.js/releases/latest) or use a [Chart.js CDN](https://cdnjs.com/libraries/Chart.js). Detailed installation instructions can be found on the [installation](./getting-started/installation.md) page. +You can download the latest version of Chart.js from the [GitHub releases](https://github.com/chartjs/Chart.js/releases/latest) or use a [Chart.js CDN](https://www.jsdelivr.com/package/npm/chart.js). Detailed installation instructions can be found on the [installation](./getting-started/installation.md) page. ## Creating a Chart It's easy to get started with Chart.js. All that's required is the script included in your page along with a single `` node to render the chart. -In this example, we create a bar chart for a single dataset and render that in our page. You can see all the ways to use Chart.js in the [usage documentation](./getting-started/usage.md) +In this example, we create a bar chart for a single dataset and render that in our page. You can see all the ways to use Chart.js in the [usage documentation](./getting-started/usage.md). ```html + ``` Now, we can create a chart. We add a script to our page: @@ -24,12 +24,12 @@ var chart = new Chart(ctx, { // The data for our dataset data: { - labels: ["January", "February", "March", "April", "May", "June", "July"], + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], datasets: [{ - label: "My First dataset", + label: 'My First dataset', backgroundColor: 'rgb(255, 99, 132)', borderColor: 'rgb(255, 99, 132)', - data: [0, 10, 5, 2, 20, 30, 45], + data: [0, 10, 5, 2, 20, 30, 45] }] }, @@ -40,4 +40,4 @@ var chart = new Chart(ctx, { It's that easy to get started using Chart.js! From here you can explore the many options that can help you customise your charts with scales, tooltips, labels, colors, custom actions, and much more. -There are many examples of Chart.js that are available in the `/samples` folder of `Chart.js.zip` that is attached to every [release](https://github.com/chartjs/Chart.js/releases). \ No newline at end of file +All our examples are [available online](https://www.chartjs.org/samples/latest/) but you can also download the `Chart.js.zip` archive attached to every [release](https://github.com/chartjs/Chart.js/releases) to experiment with our samples locally from the `/samples` folder. diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 00b19b059e4..b5121212811 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -17,6 +17,7 @@ bower install chart.js --save ``` ## CDN + ### CDNJS [![cdnjs](https://img.shields.io/cdnjs/v/Chart.js.svg?style=flat-square&maxAge=600)](https://cdnjs.com/libraries/Chart.js) @@ -27,7 +28,7 @@ https://cdnjs.com/libraries/Chart.js ### jsDelivr [![jsdelivr](https://img.shields.io/npm/v/chart.js.svg?label=jsdelivr&style=flat-square&maxAge=600)](https://cdn.jsdelivr.net/npm/chart.js@latest/dist/) [![jsdelivr hits](https://data.jsdelivr.com/v1/package/npm/chart.js/badge)](https://www.jsdelivr.com/package/npm/chart.js) -Chart.js built files are also available through [jsDelivr](http://www.jsdelivr.com/): +Chart.js built files are also available through [jsDelivr](https://www.jsdelivr.com/): https://www.jsdelivr.com/package/npm/chart.js?path=dist @@ -38,20 +39,20 @@ You can download the latest version of [Chart.js on GitHub](https://github.com/c If you download or clone the repository, you must [build](../developers/contributing.md#building-and-testing) Chart.js to generate the dist files. Chart.js no longer comes with prebuilt release versions, so an alternative option to downloading the repo is **strongly** advised. -# Selecting the Correct Build +## Selecting the Correct Build -Chart.js provides two different builds for you to choose: `Stand-Alone Build`, `Bundled Build`. +Chart.js provides two different builds for you to choose: **Stand-Alone Build**, **Bundled Build**. -## Stand-Alone Build +### Stand-Alone Build Files: * `dist/Chart.js` * `dist/Chart.min.js` -The stand-alone build includes Chart.js as well as the color parsing library. If this version is used, you are required to include [Moment.js](http://momentjs.com/) before Chart.js for the functionality of the time axis. +The stand-alone build includes Chart.js as well as the color parsing library. If this version is used, you are required to include [Moment.js](https://momentjs.com/) before Chart.js for the functionality of the time axis. -## Bundled Build +### Bundled Build Files: * `dist/Chart.bundle.js` * `dist/Chart.bundle.min.js` -The bundled build includes Moment.js in a single file. You should use this version if you require time axes and want to include a single file. You should not use this build if your application already included Moment.js. Otherwise, Moment.js will be included twice which results in increasing page load time and possible version compatability issues. The Moment.js version in the bundled build is private to Chart.js so if you want to use Moment.js yourself, it's better to use Chart.js (non bundled) and import Moment.js manually. +The bundled build includes Moment.js in a single file. You should use this version if you require time axes and want to include a single file. You should not use this build if your application already included Moment.js. Otherwise, Moment.js will be included twice which results in increasing page load time and possible version compatibility issues. The Moment.js version in the bundled build is private to Chart.js so if you want to use Moment.js yourself, it's better to use Chart.js (non bundled) and import Moment.js manually. diff --git a/docs/getting-started/integration.md b/docs/getting-started/integration.md index 95ccbc46d0a..e07a4c74783 100644 --- a/docs/getting-started/integration.md +++ b/docs/getting-started/integration.md @@ -11,26 +11,91 @@ Chart.js can be integrated with plain JavaScript or with different module loader ``` -## Webpack +## Common JS ```javascript -import Chart from 'chart.js'; +var Chart = require('chart.js'); var myChart = new Chart(ctx, {...}); ``` -## Common JS +## Bundlers (Webpack, Rollup, etc.) ```javascript -var Chart = require('chart.js'); +import Chart from 'chart.js'; var myChart = new Chart(ctx, {...}); ``` +**Note:** Moment.js is installed along Chart.js as dependency. If you don't want to use Moment.js (either because you use a different date adapter or simply because don't need time functionalities), you will have to configure your bundler to exclude this dependency (e.g. using [`externals` for Webpack](https://webpack.js.org/configuration/externals/) or [`external` for Rollup](https://rollupjs.org/guide/en#peer-dependencies)). + +```javascript +// Webpack +{ + externals: { + moment: 'moment' + } +} +``` + +```javascript +// Rollup +{ + external: { + ['moment'] + } +} +``` + ## Require JS +**Important:** RequireJS [can **not** load CommonJS module as is](https://requirejs.org/docs/commonjs.html#intro), so be sure to require one of the UMD builds instead (i.e. `dist/Chart.js`, `dist/Chart.min.js`, etc.). + ```javascript -require(['path/to/chartjs/dist/Chart.js'], function(Chart){ +require(['path/to/chartjs/dist/Chart.min.js'], function(Chart){ var myChart = new Chart(ctx, {...}); }); ``` -> **Important:** RequireJS [can **not** load CommonJS module as is](http://www.requirejs.org/docs/commonjs.html#intro), so be sure to require one of the built UMD files instead (i.e. `dist/Chart.js`, `dist/Chart.min.js`, etc.). +**Note:** starting v2.8, Moment.js is an optional dependency for `Chart.js` and `Chart.min.js`. In order to use the time scale with Moment.js, you need to make sure Moment.js is fully loaded **before** requiring Chart.js. You can either use a shim: + +```javascript +require.config({ + shim: { + 'chartjs': { + deps: ['moment'] // enforce moment to be loaded before chartjs + } + }, + paths: { + 'chartjs': 'path/to/chartjs/dist/Chart.min.js', + 'moment': 'path/to/moment' + } +}); + +require(['chartjs'], function(Chart) { + new Chart(ctx, {...}); +}); +``` + +or simply use two nested `require()`: + +```javascript +require(['moment'], function() { + require(['chartjs'], function(Chart) { + new Chart(ctx, {...}); + }); +}); +``` + +## Content Security Policy + +By default, Chart.js injects CSS directly into the DOM. For webpages secured using [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), this requires to allow `style-src 'unsafe-inline'`. For stricter CSP environments, where only `style-src 'self'` is allowed, the following CSS file needs to be manually added to your webpage: + +```html + +``` + +And the style injection must be turned off **before creating the first chart**: + +```javascript +// Disable automatic style injection +Chart.platform.disableCSSInjection = true; +``` diff --git a/docs/getting-started/usage.md b/docs/getting-started/usage.md index 739c838596c..0a0d48b9962 100644 --- a/docs/getting-started/usage.md +++ b/docs/getting-started/usage.md @@ -11,10 +11,10 @@ To create a chart, we need to instantiate the `Chart` class. To do this, we need ```javascript // Any of the following formats may be used -var ctx = document.getElementById("myChart"); -var ctx = document.getElementById("myChart").getContext("2d"); -var ctx = $("#myChart"); -var ctx = "myChart"; +var ctx = document.getElementById('myChart'); +var ctx = document.getElementById('myChart').getContext('2d'); +var ctx = $('#myChart'); +var ctx = 'myChart'; ``` Once you have the element or context, you're ready to instantiate a pre-defined chart-type or create your own! @@ -24,11 +24,11 @@ The following example instantiates a bar chart showing the number of votes for d ```html -``` \ No newline at end of file +``` diff --git a/docs/notes/README.md b/docs/notes/README.md index 2795faebc85..94d9a69f2b2 100644 --- a/docs/notes/README.md +++ b/docs/notes/README.md @@ -1 +1 @@ -# Additional Notes \ No newline at end of file +# Additional Notes diff --git a/docs/notes/comparison.md b/docs/notes/comparison.md index 3cb9c99af83..b7a72316392 100644 --- a/docs/notes/comparison.md +++ b/docs/notes/comparison.md @@ -9,7 +9,7 @@ Library Features | SVG | | ✓ | ✓ | ✓ | | Built-in Charts | ✓ | | ✓ | ✓ | | 8+ Chart Types | ✓ | ✓ | ✓ | | -| Extendable to Custom Charts | ✓ | ✓ | | | +| Extendable to Custom Charts | ✓ | ✓ | | | | Supports Modern Browsers | ✓ | ✓ | ✓ | ✓ | | Extensive Documentation | ✓ | ✓ | ✓ | ✓ | | Open Source | ✓ | ✓ | | ✓ | @@ -24,9 +24,8 @@ Built in Chart Types | Horizontal Bar | ✓ | ✓ | ✓ | | Pie/Doughnut | ✓ | ✓ | ✓ | | Polar Area | ✓ | ✓ | | -| Radar | ✓ | | | +| Radar | ✓ | | | | Scatter | ✓ | ✓ | ✓ | | Bubble | ✓ | | | | Gauges | | ✓ | | | Maps (Heat/Tree/etc.) | | ✓ | | - diff --git a/docs/notes/extensions.md b/docs/notes/extensions.md index 97f70e8fadd..d66989b1592 100644 --- a/docs/notes/extensions.md +++ b/docs/notes/extensions.md @@ -1,66 +1 @@ -# Popular Extensions - -Many extensions can be found on the [Chart.js GitHub organization](https://github.com/chartjs) or on the [npm registry](https://www.npmjs.com/search?q=chartjs-). - -## Charts - - - chartjs-chart-financial - Adds financial chart types such as a candlestick. - - Chart.BarFunnel.js - Adds a bar funnel chart type. - - Chart.LinearGauge.js - Adds a linear gauge chart type. - - Chart.Smith.js - Adds a smith chart type. - -In addition, many charts can be found on the [npm registry](https://www.npmjs.com/search?q=chartjs-chart-). - -## Plugins - - - chartjs-plugin-annotation - Draws lines and boxes on chart area. - - chartjs-plugin-datalabels - Displays labels on data for any type of charts. - - chartjs-plugin-deferred - Defers initial chart update until chart scrolls into viewport. - - chartjs-plugin-draggable - Makes select chart elements draggable with the mouse. - - chartjs-plugin-stacked100 - Draws 100% stacked bar chart. - - chartjs-plugin-streaming - Enables to create live streaming charts. - - chartjs-plugin-style - Provides more styling options. - - chartjs-plugin-waterfall - Enables easy use of waterfall charts. - - chartjs-plugin-zoom - Enables zooming and panning on charts. - -In addition, many plugins can be found on the [npm registry](https://www.npmjs.com/search?q=chartjs-plugin-). - -## Integrations - -### Angular (v2+) - - - emn178/angular2-chartjs - - valor-software/ng2-charts - -### Angular (v1) - - angular-chart.js - - tc-angular-chartjs - - angular-chartjs - - Angular Chart-js Directive - -### React - - react-chartjs2 - - react-chartjs-2 - -### Django - - Django JChart - - Django Chartjs - -### Ruby on Rails - - chartjs-ror - -### Laravel - - laravel-chartjs - -### Vue.js - - vue-chartjs - -### Java - - Chart.java - - Wicked-Charts - -### GWT (Google Web toolkit) - - Charba - -### Ember.js - - ember-cli-chart +!REDIRECT "https://github.com/chartjs/awesome" diff --git a/docs/notes/license.md b/docs/notes/license.md index b933686df54..9bc3c679231 100644 --- a/docs/notes/license.md +++ b/docs/notes/license.md @@ -1,3 +1,3 @@ # License -Chart.js is open source and available under the MIT license. \ No newline at end of file +Chart.js is open source and available under the MIT license. diff --git a/gulpfile.js b/gulpfile.js index f6795fa7f56..861a9d1cfcd 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,67 +1,57 @@ var gulp = require('gulp'); -var concat = require('gulp-concat'); -var connect = require('gulp-connect'); var eslint = require('gulp-eslint'); var file = require('gulp-file'); -var insert = require('gulp-insert'); var replace = require('gulp-replace'); var size = require('gulp-size'); var streamify = require('gulp-streamify'); -var uglify = require('gulp-uglify'); -var util = require('gulp-util'); +var terser = require('gulp-terser'); var zip = require('gulp-zip'); -var exec = require('child-process-promise').exec; +var exec = require('child_process').exec; var karma = require('karma'); -var browserify = require('browserify'); -var source = require('vinyl-source-stream'); var merge = require('merge-stream'); -var collapse = require('bundle-collapser/plugin'); var yargs = require('yargs'); var path = require('path'); -var fs = require('fs'); var htmllint = require('gulp-htmllint'); var pkg = require('./package.json'); var argv = yargs - .option('force-output', {default: false}) - .option('silent-errors', {default: false}) .option('verbose', {default: false}) - .argv + .argv; var srcDir = './src/'; var outDir = './dist/'; -var header = "/*!\n" + - " * Chart.js\n" + - " * http://chartjs.org/\n" + - " * Version: {{ version }}\n" + - " *\n" + - " * Copyright " + (new Date().getFullYear()) + " Chart.js Contributors\n" + - " * Released under the MIT license\n" + - " * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md\n" + - " */\n"; - -if (argv.verbose) { - util.log("Gulp running with options: " + JSON.stringify(argv, null, 2)); -} - gulp.task('bower', bowerTask); gulp.task('build', buildTask); gulp.task('package', packageTask); -gulp.task('watch', watchTask); -gulp.task('lint', ['lint-html', 'lint-js']); gulp.task('lint-html', lintHtmlTask); gulp.task('lint-js', lintJsTask); +gulp.task('lint', gulp.parallel('lint-html', 'lint-js')); gulp.task('docs', docsTask); -gulp.task('test', ['lint', 'unittest']); -gulp.task('size', ['library-size', 'module-sizes']); -gulp.task('server', serverTask); gulp.task('unittest', unittestTask); +gulp.task('test', gulp.parallel('lint', 'unittest')); gulp.task('library-size', librarySizeTask); gulp.task('module-sizes', moduleSizesTask); -gulp.task('_open', _openTask); -gulp.task('dev', ['server', 'default']); -gulp.task('default', ['build', 'watch']); +gulp.task('size', gulp.parallel('library-size', 'module-sizes')); +gulp.task('default', gulp.parallel('build')); + +function run(bin, args, done) { + return new Promise(function(resolve, reject) { + var exe = '"' + process.execPath + '"'; + var src = require.resolve(bin); + var ps = exec([exe, src].concat(args || []).join(' ')); + + ps.stdout.pipe(process.stdout); + ps.stderr.pipe(process.stderr); + ps.on('close', function(error) { + if (error) { + reject(error); + } else { + resolve(); + } + }); + }); +} /** * Generates the bower.json manifest file which will be pushed along release tags. @@ -74,7 +64,7 @@ function bowerTask() { homepage: pkg.homepage, license: pkg.license, version: pkg.version, - main: outDir + "Chart.js", + main: outDir + 'Chart.js', ignore: [ '.github', '.codeclimate.yml', @@ -90,59 +80,13 @@ function bowerTask() { } function buildTask() { - - var errorHandler = function (err) { - if(argv.forceOutput) { - var browserError = 'console.error("Gulp: ' + err.toString() + '")'; - ['Chart', 'Chart.min', 'Chart.bundle', 'Chart.bundle.min'].forEach(function(fileName) { - fs.writeFileSync(outDir+fileName+'.js', browserError); - }); - } - if(argv.silentErrors) { - util.log(util.colors.red('[Error]'), err.toString()); - this.emit('end'); - } else { - throw err; - } - } - - var bundled = browserify('./src/chart.js', { standalone: 'Chart' }) - .plugin(collapse) - .bundle() - .on('error', errorHandler) - .pipe(source('Chart.bundle.js')) - .pipe(insert.prepend(header)) - .pipe(streamify(replace('{{ version }}', pkg.version))) - .pipe(gulp.dest(outDir)) - .pipe(streamify(uglify())) - .pipe(insert.prepend(header)) - .pipe(streamify(replace('{{ version }}', pkg.version))) - .pipe(streamify(concat('Chart.bundle.min.js'))) - .pipe(gulp.dest(outDir)); - - var nonBundled = browserify('./src/chart.js', { standalone: 'Chart' }) - .ignore('moment') - .plugin(collapse) - .bundle() - .on('error', errorHandler) - .pipe(source('Chart.js')) - .pipe(insert.prepend(header)) - .pipe(streamify(replace('{{ version }}', pkg.version))) - .pipe(gulp.dest(outDir)) - .pipe(streamify(uglify())) - .pipe(insert.prepend(header)) - .pipe(streamify(replace('{{ version }}', pkg.version))) - .pipe(streamify(concat('Chart.min.js'))) - .pipe(gulp.dest(outDir)); - - return merge(bundled, nonBundled); - + return run('rollup/bin/rollup', ['-c', argv.watch ? '--watch' : '']); } function packageTask() { return merge( // gather "regular" files landing in the package root - gulp.src([outDir + '*.js', 'LICENSE.md']), + gulp.src([outDir + '*.js', outDir + '*.css', 'LICENSE.md']), // since we moved the dist files one folder up (package root), we need to rewrite // samples src="../dist/ to src="../ and then copy them in the /samples directory. @@ -185,40 +129,22 @@ function lintHtmlTask() { })); } -function docsTask(done) { - const script = require.resolve('gitbook-cli/bin/gitbook.js'); - const cmd = process.execPath; +function docsTask() { + var bin = 'gitbook-cli/bin/gitbook.js'; + var cmd = argv.watch ? 'serve' : 'build'; - exec([cmd, script, 'install', './'].join(' ')).then(() => { - return exec([cmd, script, argv.watch ? 'serve' : 'build', './', './dist/docs'].join(' ')); - }).catch((err) => { - console.error(err.stdout); - }).then(() => { - done(); - }); -} - -function startTest() { - return [ - {pattern: './test/fixtures/**/*.json', included: false}, - {pattern: './test/fixtures/**/*.png', included: false}, - './node_modules/moment/min/moment.min.js', - './test/jasmine.index.js', - './src/**/*.js', - ].concat( - argv.inputs ? - argv.inputs.split(';') : - ['./test/specs/**/*.js'] - ); + return run(bin, ['install', './']) + .then(() => run(bin, [cmd, './', './dist/docs'])); } function unittestTask(done) { new karma.Server({ configFile: path.join(__dirname, 'karma.conf.js'), singleRun: !argv.watch, - files: startTest(), args: { - coverage: !!argv.coverage + coverage: !!argv.coverage, + inputs: (argv.inputs || 'test/specs/**/*.js').split(';'), + watch: argv.watch } }, // https://github.com/karma-runner/gulp-karma/issues/18 @@ -237,29 +163,9 @@ function librarySizeTask() { function moduleSizesTask() { return gulp.src(srcDir + '**/*.js') - .pipe(uglify()) + .pipe(terser()) .pipe(size({ showFiles: true, gzip: true })); } - -function watchTask() { - if (util.env.test) { - return gulp.watch('./src/**', ['build', 'unittest', 'unittestWatch']); - } - return gulp.watch('./src/**', ['build']); -} - -function serverTask() { - connect.server({ - port: 8000 - }); -} - -// Convenience task for opening the project straight from the command line - -function _openTask() { - exec('open http://localhost:8000'); - exec('subl .'); -} diff --git a/karma.conf.js b/karma.conf.js index 5bb73ef03a0..d7aae642a2e 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,11 +1,29 @@ -/* eslint camelcase: 0 */ +/* eslint-env es6 */ + +const commonjs = require('rollup-plugin-commonjs'); +const istanbul = require('rollup-plugin-istanbul'); +const resolve = require('rollup-plugin-node-resolve'); +const builds = require('./rollup.config'); module.exports = function(karma) { - var args = karma.args || {}; - var config = { - frameworks: ['browserify', 'jasmine'], + const args = karma.args || {}; + + // Use the same rollup config as our dist files: when debugging (--watch), + // we will prefer the unminified build which is easier to browse and works + // better with source mapping. In other cases, pick the minified build to + // make sure that the minification process (terser) doesn't break anything. + const regex = args.watch ? /Chart\.js$/ : /Chart\.min\.js$/; + const build = builds.filter(v => v.output.file.match(regex))[0]; + + if (args.watch) { + build.output.sourcemap = 'inline'; + } + + karma.set({ + frameworks: ['jasmine'], reporters: ['progress', 'kjhtml'], browsers: ['chrome', 'firefox'], + logLevel: karma.LOG_WARN, // Explicitly disable hardware acceleration to make image // diff more stable when ran on Travis and dev machine. @@ -25,39 +43,66 @@ module.exports = function(karma) { } }, + files: [ + {pattern: 'test/fixtures/**/*.js', included: false}, + {pattern: 'test/fixtures/**/*.json', included: false}, + {pattern: 'test/fixtures/**/*.png', included: false}, + 'node_modules/moment/min/moment.min.js', + 'test/index.js', + 'src/index.js' + ].concat(args.inputs), + preprocessors: { - './test/jasmine.index.js': ['browserify'], - './src/**/*.js': ['browserify'] + 'test/index.js': ['rollup'], + 'src/index.js': ['sources'] }, - browserify: { - debug: true + rollupPreprocessor: { + plugins: [ + resolve(), + commonjs() + ], + output: { + name: 'test', + format: 'umd' + } + }, + + customPreprocessors: { + sources: { + base: 'rollup', + options: build + } }, // These settings deal with browser disconnects. We had seen test flakiness from Firefox // [Firefox 56.0.0 (Linux 0.0.0)]: Disconnected (1 times), because no message in 10000 ms. // https://github.com/jasmine/jasmine/issues/1327#issuecomment-332939551 browserDisconnectTolerance: 3 - }; + }); // https://swizec.com/blog/how-to-run-javascript-tests-in-chrome-on-travis/swizec/6647 if (process.env.TRAVIS) { - config.customLaunchers.chrome.flags.push('--no-sandbox'); + karma.customLaunchers.chrome.flags.push('--no-sandbox'); } if (args.coverage) { - config.reporters.push('coverage'); - config.browserify.transform = ['browserify-istanbul']; - - // https://github.com/karma-runner/karma-coverage/blob/master/docs/configuration.md - config.coverageReporter = { + karma.reporters.push('coverage'); + karma.coverageReporter = { dir: 'coverage/', reporters: [ - {type: 'html', subdir: 'report-html'}, - {type: 'lcovonly', subdir: '.', file: 'lcov.info'} + {type: 'html', subdir: 'html'}, + {type: 'lcovonly', subdir: '.'} ] }; + [ + karma.rollupPreprocessor, + karma.customPreprocessors.sources.options + ].forEach(v => { + (v.plugins || (v.plugins = [])).unshift( + istanbul({ + include: 'src/**/*.js' + })); + }); } - - karma.set(config); }; diff --git a/package.json b/package.json index 30e365f7467..9d72920c053 100644 --- a/package.json +++ b/package.json @@ -1,54 +1,66 @@ { "name": "chart.js", - "homepage": "http://www.chartjs.org", + "homepage": "https://www.chartjs.org", "description": "Simple HTML5 charts using the canvas element.", - "version": "2.7.3", + "version": "2.8.0", "license": "MIT", - "main": "src/chart.js", + "jsdelivr": "dist/Chart.min.js", + "unpkg": "dist/Chart.min.js", + "main": "dist/Chart.js", + "keywords": [ + "canvas", + "charts", + "data", + "graphs", + "html5", + "responsive" + ], "repository": { "type": "git", "url": "https://github.com/chartjs/Chart.js.git" }, + "bugs": { + "url": "https://github.com/chartjs/Chart.js/issues" + }, + "files": [ + "bower.json", + "composer.json", + "dist/*.css", + "dist/*.js" + ], "devDependencies": { - "browserify": "^14.5.0", - "browserify-istanbul": "^3.0.1", - "bundle-collapser": "^1.3.0", - "child-process-promise": "^2.2.1", + "clean-css": "^4.2.1", "coveralls": "^3.0.0", - "eslint": "^4.9.0", + "eslint": "^5.9.0", "eslint-config-chartjs": "^0.1.0", - "eslint-plugin-html": "^4.0.2", + "eslint-plugin-html": "^5.0.0", "gitbook-cli": "^2.3.2", - "gulp": "3.9.x", - "gulp-concat": "~2.6.x", - "gulp-connect": "~5.0.0", - "gulp-eslint": "^4.0.0", - "gulp-file": "^0.3.0", - "gulp-htmllint": "^0.0.15", - "gulp-insert": "~0.5.0", - "gulp-replace": "^0.6.1", - "gulp-size": "~2.1.0", + "gulp": "^4.0.0", + "gulp-eslint": "^5.0.0", + "gulp-file": "^0.4.0", + "gulp-htmllint": "^0.0.16", + "gulp-replace": "^1.0.0", + "gulp-size": "^3.0.0", "gulp-streamify": "^1.0.2", - "gulp-uglify": "~3.0.x", - "gulp-util": "~3.0.x", - "gulp-zip": "~4.0.0", - "jasmine": "^2.8.0", - "jasmine-core": "^2.8.0", - "karma": "^1.7.1", - "karma-browserify": "^5.1.1", + "gulp-terser": "^1.1.6", + "gulp-zip": "^4.2.0", + "jasmine": "^3.3.0", + "jasmine-core": "^3.3.0", + "karma": "^4.0.0", "karma-chrome-launcher": "^2.2.0", "karma-coverage": "^1.1.1", "karma-firefox-launcher": "^1.0.1", - "karma-jasmine": "^1.1.0", - "karma-jasmine-html-reporter": "^0.2.2", + "karma-jasmine": "^2.0.1", + "karma-jasmine-html-reporter": "^1.4.0", + "karma-rollup-preprocessor": "^6.1.1", "merge-stream": "^1.0.1", "pixelmatch": "^4.0.2", - "vinyl-source-stream": "^1.1.0", - "watchify": "^3.9.0", - "yargs": "^9.0.1" - }, - "spm": { - "main": "Chart.js" + "rollup": "^0.67.4", + "rollup-plugin-commonjs": "^9.2.0", + "rollup-plugin-istanbul": "^2.0.1", + "rollup-plugin-node-resolve": "^3.4.0", + "rollup-plugin-terser": "^3.0.0", + "yargs": "^12.0.5" }, "dependencies": { "chartjs-color": "^2.1.0", diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 00000000000..fc53f1a7460 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,119 @@ +/* eslint-env es6 */ + +const commonjs = require('rollup-plugin-commonjs'); +const resolve = require('rollup-plugin-node-resolve'); +const terser = require('rollup-plugin-terser').terser; +const optional = require('./rollup.plugins').optional; +const stylesheet = require('./rollup.plugins').stylesheet; +const pkg = require('./package.json'); + +const input = 'src/index.js'; +const banner = `/*! + * Chart.js v${pkg.version} + * ${pkg.homepage} + * (c) ${new Date().getFullYear()} Chart.js Contributors + * Released under the MIT License + */`; + +module.exports = [ + // UMD builds (excluding moment) + // dist/Chart.min.js + // dist/Chart.js + { + input: input, + plugins: [ + resolve(), + commonjs(), + stylesheet({ + extract: true + }), + optional({ + include: ['moment'] + }) + ], + output: { + name: 'Chart', + file: 'dist/Chart.js', + banner: banner, + format: 'umd', + indent: false, + globals: { + moment: 'moment' + } + }, + external: [ + 'moment' + ] + }, + { + input: input, + plugins: [ + resolve(), + commonjs(), + optional({ + include: ['moment'] + }), + stylesheet({ + extract: true, + minify: true + }), + terser({ + output: { + preamble: banner + } + }) + ], + output: { + name: 'Chart', + file: 'dist/Chart.min.js', + format: 'umd', + indent: false, + globals: { + moment: 'moment' + } + }, + external: [ + 'moment' + ] + }, + + // UMD builds (including moment) + // dist/Chart.bundle.min.js + // dist/Chart.bundle.js + { + input: input, + plugins: [ + resolve(), + commonjs(), + stylesheet() + ], + output: { + name: 'Chart', + file: 'dist/Chart.bundle.js', + banner: banner, + format: 'umd', + indent: false + } + }, + { + input: input, + plugins: [ + resolve(), + commonjs(), + stylesheet({ + minify: true + }), + terser({ + output: { + preamble: banner + } + }) + ], + output: { + name: 'Chart', + file: 'dist/Chart.bundle.min.js', + format: 'umd', + indent: false + } + } +]; diff --git a/rollup.plugins.js b/rollup.plugins.js new file mode 100644 index 00000000000..967c0e59254 --- /dev/null +++ b/rollup.plugins.js @@ -0,0 +1,108 @@ +/* eslint-env es6 */ +const cleancss = require('clean-css'); +const path = require('path'); + +const UMD_WRAPPER_RE = /(\(function \(global, factory\) \{)((?:\s.*?)*)(\}\(this,)/; +const CJS_FACTORY_RE = /(module.exports = )(factory\(.*?\))( :)/; +const AMD_FACTORY_RE = /(define\()(.*?, factory)(\) :)/; + +function optional(config = {}) { + return { + name: 'optional', + renderChunk(code, chunk, options) { + if (options.format !== 'umd') { + this.error('only UMD format is currently supported'); + } + + const wrapper = UMD_WRAPPER_RE.exec(code); + const include = config.include; + if (!wrapper) { + this.error('failed to parse the UMD wrapper'); + } + + let content = wrapper[2]; + let factory = (CJS_FACTORY_RE.exec(content) || [])[2]; + let updated = false; + + for (let lib of chunk.imports) { + if (!include || include.indexOf(lib) !== -1) { + const regex = new RegExp(`require\\('${lib}'\\)`); + if (!regex.test(factory)) { + this.error(`failed to parse the CJS require for ${lib}`); + } + + // We need to write inline try / catch with explicit require + // in order to enable statical extraction of dependencies: + // try { return require('moment'); } catch(e) {} + const loader = `function() { try { return require('${lib}'); } catch(e) { } }()`; + factory = factory.replace(regex, loader); + updated = true; + } + } + + if (!updated) { + return; + } + + // Replace the CJS factory by our updated one. + content = content.replace(CJS_FACTORY_RE, `$1${factory}$3`); + + // Replace the AMD factory by our updated one: we need to use the + // following AMD form in order to be able to try/catch require: + // define(['require'], function(require) { ... require(...); ... }) + // https://github.com/amdjs/amdjs-api/wiki/AMD#using-require-and-exports + content = content.replace(AMD_FACTORY_RE, `$1['require'], function(require) { return ${factory}; }$3`); + + return code.replace(UMD_WRAPPER_RE, `$1${content}$3`); + } + }; +} + +// https://github.com/chartjs/Chart.js/issues/5208 +function stylesheet(config = {}) { + const minifier = new cleancss(); + const styles = []; + + return { + name: 'stylesheet', + transform(code, id) { + // Note that 'id' can be mapped to a CJS proxy import, in which case + // 'id' will start with 'commonjs-proxy', so let's first check if we + // are importing an existing css file (i.e. startsWith()). + if (!id.startsWith(path.resolve('.')) || !id.endsWith('.css')) { + return; + } + + if (config.minify) { + code = minifier.minify(code).styles; + } + + // keep track of all imported stylesheets (already minified) + styles.push(code); + + return { + code: 'export default ' + JSON.stringify(code) + }; + }, + generateBundle(opts, bundle) { + if (!config.extract) { + return; + } + + const entry = Object.keys(bundle).find(v => bundle[v].isEntry); + const name = (entry || '').replace(/\.js$/i, '.css'); + if (!name) { + this.error('failed to guess the output file name'); + } + + bundle[name] = { + code: styles.filter(v => !!v).join('') + }; + } + }; +} + +module.exports = { + optional, + stylesheet +}; diff --git a/samples/advanced/content-security-policy.css b/samples/advanced/content-security-policy.css new file mode 100644 index 00000000000..8e5b8fd8cbb --- /dev/null +++ b/samples/advanced/content-security-policy.css @@ -0,0 +1,20 @@ +.content { + max-width: 640px; + margin: auto; + padding: 1rem; +} + +.note { + font-family: sans-serif; + color: #5050a0; + line-height: 1.4; + margin-bottom: 1rem; + padding: 1rem; +} + +code { + background-color: #f5f5ff; + border: 1px solid #d0d0fa; + border-radius: 4px; + padding: 0.05rem 0.25rem; +} diff --git a/samples/advanced/content-security-policy.html b/samples/advanced/content-security-policy.html new file mode 100644 index 00000000000..fb2805cdc06 --- /dev/null +++ b/samples/advanced/content-security-policy.html @@ -0,0 +1,27 @@ + + + + + + + + Scriptable > Bubble | Chart.js sample + + + + + + + +
+
+ In order to support a strict content security policy (default-src 'self'), + this page manually loads Chart.min.css and turns off the automatic style + injection by setting Chart.platform.disableCSSInjection = true;. +
+
+ +
+
+ + diff --git a/samples/advanced/content-security-policy.js b/samples/advanced/content-security-policy.js new file mode 100644 index 00000000000..a185332f74b --- /dev/null +++ b/samples/advanced/content-security-policy.js @@ -0,0 +1,54 @@ +var utils = Samples.utils; + +// CSP: disable automatic style injection +Chart.platform.disableCSSInjection = true; + +utils.srand(110); + +function generateData() { + var DATA_COUNT = 16; + var MIN_XY = -150; + var MAX_XY = 100; + var data = []; + var i; + + for (i = 0; i < DATA_COUNT; ++i) { + data.push({ + x: utils.rand(MIN_XY, MAX_XY), + y: utils.rand(MIN_XY, MAX_XY), + v: utils.rand(0, 1000) + }); + } + + return data; +} + +window.addEventListener('load', function() { + new Chart('chart-0', { + type: 'bubble', + data: { + datasets: [{ + backgroundColor: utils.color(0), + data: generateData() + }, { + backgroundColor: utils.color(1), + data: generateData() + }] + }, + options: { + aspectRatio: 1, + legend: false, + tooltip: false, + elements: { + point: { + radius: function(context) { + var value = context.dataset.data[context.dataIndex]; + var size = context.chart.width; + var base = Math.abs(value.v) / 1000; + return (size / 24) * base; + } + } + } + } + }); +}); diff --git a/samples/advanced/data-labelling.html b/samples/advanced/data-labelling.html deleted file mode 100644 index 52eb07b8fd3..00000000000 --- a/samples/advanced/data-labelling.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Labelling Data Points - - - - - - -
- -
- - - - - diff --git a/samples/advanced/progress-bar.html b/samples/advanced/progress-bar.html index b9c72446e59..4736546ba48 100644 --- a/samples/advanced/progress-bar.html +++ b/samples/advanced/progress-bar.html @@ -2,7 +2,7 @@ Animation Callbacks - + + + + +
+
+ +
+ + + + diff --git a/samples/legend/point-style.html b/samples/legend/point-style.html index b7acea4bd84..40c5cdbfd12 100644 --- a/samples/legend/point-style.html +++ b/samples/legend/point-style.html @@ -3,7 +3,7 @@ Legend Point Style - +