Give the boot to chartjs-adapter-moment (#7155)

Remove default of using chartjs-adapter-moment
This commit is contained in:
Jukka Kurkela 2020-02-28 02:40:31 +02:00 committed by GitHub
parent 3c1e04f928
commit df3c73cc5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 49 additions and 209 deletions

View File

@ -4,7 +4,7 @@ The time scale is used to display times and dates. When building its ticks, it w
## Date Adapters ## Date Adapters
The time scale requires both a date library and corresponding adapter to be present. By default, Chart.js includes an adapter for Moment.js. You may wish to choose from [other available adapters](https://github.com/chartjs/awesome#adapters) instead. The time scale **requires** both a date library and corresponding adapter to be present. Please choose from the [available adapters](https://github.com/chartjs/awesome#adapters).
## Data Sets ## Data Sets

View File

@ -35,32 +35,14 @@ require(['path/to/chartjs/dist/Chart.min.js'], function(Chart){
}); });
``` ```
**Note:** in order to use the time scale, you need to make sure [one of the available date adapters](https://github.com/chartjs/awesome#adapters) and corresponding date library are fully loaded **before** requiring Chart.js. The date adapter for Moment.js is included with Chart.js, but you still need to include Moment.js itself if this is the date adapter you choose to use. You can either use a shim: **Note:** in order to use the time scale, you need to make sure [one of the available date adapters](https://github.com/chartjs/awesome#adapters) and corresponding date library are fully loaded **after** requiring Chart.js. For this you can use nested requires:
```javascript ```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) { require(['chartjs'], function(Chart) {
new Chart(ctx, {...}); require(['moment'], function() {
}); require(['chartjs-adapter-moment'], function() {
``` new Chart(ctx, {...});
});
or simply use two nested `require()`:
```javascript
require(['moment'], function() {
require(['chartjs'], function(Chart) {
new Chart(ctx, {...});
}); });
}); });
``` ```

View File

@ -15,7 +15,7 @@ Chart.js 3.0 introduces a number of breaking changes. Chart.js 2.0 was released
### Setup and installation ### Setup and installation
* Chart.js is no longer providing the `Chart.bundle.js` and `Chart.bundle.min.js`. Please see the [installation](installation.md) and [integration](integration.md) docs for details on the recommended way to setup Chart.js if you were using these builds. * Chart.js is no longer providing the `Chart.bundle.js` and `Chart.bundle.min.js`. Please see the [installation](installation.md) and [integration](integration.md) docs for details on the recommended way to setup Chart.js if you were using these builds.
* `moment` is no longer specified as an npm dependency. If you are using the time scale, you must include one of [the available adapters](https://github.com/chartjs/awesome#adapters) and corresponding date library. If you are using a date library other than moment, you no longer need to exclude moment from your build. * `moment` is no longer specified as an npm dependency. If you are using the time scale, you must include one of [the available adapters](https://github.com/chartjs/awesome#adapters) and corresponding date library. You no longer need to exclude moment from your build.
### Ticks ### Ticks

View File

@ -55,7 +55,8 @@ module.exports = function(karma) {
{pattern: 'test/fixtures/**/*.png', included: false}, {pattern: 'test/fixtures/**/*.png', included: false},
'node_modules/moment/min/moment.min.js', 'node_modules/moment/min/moment.min.js',
'test/index.js', 'test/index.js',
'src/index.js' 'src/index.js',
'node_modules/chartjs-adapter-moment/dist/chartjs-adapter-moment.js'
].concat((args.inputs || 'test/specs/**/*.js').split(';')), ].concat((args.inputs || 'test/specs/**/*.js').split(';')),
preprocessors: { preprocessors: {

6
package-lock.json generated
View File

@ -3932,6 +3932,12 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true "dev": true
}, },
"chartjs-adapter-moment": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-0.1.1.tgz",
"integrity": "sha512-lFGCiqpn+0e6CEbEKdG1L3LYR0jnKFqtXsExzmEWXGCxdymTFSqntiWAqWAYDblL/QB3sUk881xVGzhWZdn4kQ==",
"dev": true
},
"chokidar": { "chokidar": {
"version": "2.1.8", "version": "2.1.8",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",

View File

@ -39,6 +39,7 @@
"@rollup/plugin-node-resolve": "^7.1.1", "@rollup/plugin-node-resolve": "^7.1.1",
"babel-plugin-istanbul": "^6.0.0", "babel-plugin-istanbul": "^6.0.0",
"babel-preset-es2015-rollup": "^3.0.0", "babel-preset-es2015-rollup": "^3.0.0",
"chartjs-adapter-moment": "^0.1.1",
"coveralls": "^3.0.9", "coveralls": "^3.0.9",
"eslint": "^6.8.0", "eslint": "^6.8.0",
"eslint-config-chartjs": "^0.2.0", "eslint-config-chartjs": "^0.2.0",

View File

@ -4,7 +4,6 @@
const babel = require('rollup-plugin-babel'); const babel = require('rollup-plugin-babel');
const cleanup = require('rollup-plugin-cleanup'); const cleanup = require('rollup-plugin-cleanup');
const json = require('@rollup/plugin-json'); const json = require('@rollup/plugin-json');
const optional = require('./rollup.plugins').optional;
const resolve = require('@rollup/plugin-node-resolve'); const resolve = require('@rollup/plugin-node-resolve');
const terser = require('rollup-plugin-terser').terser; const terser = require('rollup-plugin-terser').terser;
const pkg = require('./package.json'); const pkg = require('./package.json');
@ -28,9 +27,6 @@ module.exports = [
json(), json(),
resolve(), resolve(),
babel(), babel(),
optional({
include: ['moment']
}),
cleanup({ cleanup({
sourcemap: true sourcemap: true
}) })
@ -41,13 +37,7 @@ module.exports = [
banner, banner,
format: 'umd', format: 'umd',
indent: false, indent: false,
globals: {
moment: 'moment'
}
}, },
external: [
'moment'
]
}, },
{ {
input, input,
@ -55,9 +45,6 @@ module.exports = [
json(), json(),
resolve(), resolve(),
babel(), babel(),
optional({
include: ['moment']
}),
terser({ terser({
output: { output: {
preamble: banner preamble: banner
@ -69,13 +56,7 @@ module.exports = [
file: 'dist/Chart.min.js', file: 'dist/Chart.min.js',
format: 'umd', format: 'umd',
indent: false, indent: false,
globals: {
moment: 'moment'
}
}, },
external: [
'moment'
]
}, },
// ES6 builds // ES6 builds
@ -97,13 +78,7 @@ module.exports = [
banner, banner,
format: 'esm', format: 'esm',
indent: false, indent: false,
globals: {
moment: 'moment'
}
}, },
external: [
'moment'
]
}, },
{ {
input, input,
@ -122,12 +97,6 @@ module.exports = [
file: 'dist/Chart.esm.min.js', file: 'dist/Chart.esm.min.js',
format: 'esm', format: 'esm',
indent: false, indent: false,
globals: {
moment: 'moment'
}
}, },
external: [
'moment'
]
}, },
]; ];

View File

@ -1,60 +0,0 @@
/* eslint-disable import/no-commonjs */
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 (const 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`);
}
};
}
module.exports = {
optional
};

View File

@ -3,6 +3,7 @@ globals:
Chart: true Chart: true
Samples: true Samples: true
moment: true moment: true
luxon: true
randomScalingFactor: true randomScalingFactor: true
rules: rules:

View File

@ -3,8 +3,9 @@
<head> <head>
<title>Line Chart</title> <title>Line Chart</title>
<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../../dist/Chart.min.js"></script> <script src="../../dist/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luxon@1.15.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@0.2.0"></script>
<script src="../utils.js"></script> <script src="../utils.js"></script>
<style> <style>
canvas { canvas {
@ -39,14 +40,14 @@
<button id="update">update</button> <button id="update">update</button>
<script> <script>
function isFirstUnitOfPeriod(date, unit, period) { function isFirstUnitOfPeriod(date, unit, period) {
let first = date.clone().startOf(period); let first = date.startOf(period);
while (first.isoWeekday() > 5) { while (first.weekday > 5) {
first.add(1, 'days'); first = first.plus({day: 1});
} }
if (unit === 'second' || unit === 'minute' || unit === 'hour') { if (unit === 'second' || unit === 'minute' || unit === 'hour') {
first = first.hours(9).minutes(30); first = first.set({hour: 9, minute: 30});
} }
return date.isSame(first); return date === first;
} }
// Generate data between the stock market hours of 9:30am - 5pm. // Generate data between the stock market hours of 9:30am - 5pm.
@ -59,17 +60,17 @@
} }
function beforeNineThirty(date) { function beforeNineThirty(date) {
return date.hour() < 9 || (date.hour() === 9 && date.minute() < 30); return date.hour < 9 || (date.hour === 9 && date.minute < 30);
} }
function after4pm(date) { function after4pm(date) {
return date.hour() > 16 || (date.hour() === 16 && date.minute() > 0); return date.hour > 16 || (date.hour === 16 && date.minute > 0);
} }
// Returns true if outside 9:30am-4pm on a weekday // Returns true if outside 9:30am-4pm on a weekday
function outsideMarketHours(date) { function outsideMarketHours(date) {
if (date.isoWeekday() > 5) { if (date.weekday > 5) {
return true; return true;
} }
if (unitLessThanDay() && (beforeNineThirty(date) || after4pm(date))) { if (unitLessThanDay() && (beforeNineThirty(date) || after4pm(date))) {
@ -86,22 +87,24 @@
const open = randomNumber(lastClose * 0.95, lastClose * 1.05).toFixed(2); const open = randomNumber(lastClose * 0.95, lastClose * 1.05).toFixed(2);
const close = randomNumber(open * 0.95, open * 1.05).toFixed(2); const close = randomNumber(open * 0.95, open * 1.05).toFixed(2);
return { return {
t: date.valueOf(), x: date.valueOf(),
y: close y: close
}; };
} }
let date = moment('Jan 01 1990', 'MMM DD YYYY'); let date = luxon.DateTime.fromFormat('Jan 01 1990', 'LLL dd yyyy');
const now = moment(); const now = luxon.DateTime.local();
const data = []; const data = [];
const lessThanDay = unitLessThanDay(); const lessThanDay = unitLessThanDay();
for (; data.length < 600 && date.isBefore(now); date = date.clone().add(1, unit).startOf(unit)) { const plus = {};
plus[unit] = 1;
for (; data.length < 600 && date < now; date = date.plus(plus).startOf(unit)) {
if (outsideMarketHours(date)) { if (outsideMarketHours(date)) {
if (!lessThanDay || !beforeNineThirty(date)) { if (!lessThanDay || !beforeNineThirty(date)) {
date = date.clone().add(date.isoWeekday() >= 5 ? 8 - date.isoWeekday() : 1, 'day'); date = date.plus({day: date.weekday >= 5 ? 8 - date.weekday : 1});
} }
if (lessThanDay) { if (lessThanDay) {
date = date.hour(9).minute(30).second(0); date = date.set({hour: 9, minute: 30});
} }
} }
data.push(randomBar(date, data.length > 0 ? data[data.length - 1].y : 30)); data.push(randomBar(date, data.length > 0 ? data[data.length - 1].y : 30));
@ -164,7 +167,7 @@
// major ticks // major ticks
const ticks = scale.ticks; const ticks = scale.ticks;
for (let i = 0; i < ticks.length; i++) { for (let i = 0; i < ticks.length; i++) {
ticks[i].major = !majorUnit || isFirstUnitOfPeriod(moment(ticks[i].value), unit, majorUnit); ticks[i].major = !majorUnit || isFirstUnitOfPeriod(luxon.DateTime.fromMillis(ticks[i].value), unit, majorUnit);
} }
scale.ticks = ticks; scale.ticks = ticks;
} }

View File

@ -3,8 +3,8 @@
<head> <head>
<title>Line Chart - Combo Time Scale</title> <title>Line Chart - Combo Time Scale</title>
<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../../../dist/Chart.min.js"></script> <script src="../../../dist/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@1.0.0/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<script src="../../utils.js"></script> <script src="../../utils.js"></script>
<style> <style>
canvas { canvas {
@ -28,7 +28,10 @@
<button id="removeData">Remove Data</button> <button id="removeData">Remove Data</button>
<script> <script>
function newDate(days) { function newDate(days) {
return moment().startOf('day').add(days, 'd').valueOf(); var date = new Date();
date.setHours(0, 0, 0, 0);
date.setDate(date.getDate() + days);
return date.valueOf();
} }
var labels = []; var labels = [];

View File

@ -3,8 +3,9 @@
<head> <head>
<title>Time Scale Point Data</title> <title>Time Scale Point Data</title>
<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../../../dist/Chart.min.js"></script> <script src="../../../dist/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@0.1.1"></script>
<script src="../../utils.js"></script> <script src="../../utils.js"></script>
<style> <style>
canvas { canvas {

View File

@ -3,8 +3,9 @@
<head> <head>
<title>Time Scale Point Data</title> <title>Time Scale Point Data</title>
<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../../../dist/Chart.min.js"></script> <script src="../../../dist/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@0.1.1"></script>
<script src="../../utils.js"></script> <script src="../../utils.js"></script>
<style> <style>
canvas { canvas {

View File

@ -3,8 +3,9 @@
<head> <head>
<title>Line Chart</title> <title>Line Chart</title>
<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../../../dist/Chart.min.js"></script> <script src="../../../dist/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@0.1.1"></script>
<script src="../../utils.js"></script> <script src="../../utils.js"></script>
<style> <style>
canvas { canvas {

View File

@ -1,58 +0,0 @@
// TODO v3 - make this adapter external (chartjs-adapter-moment)
import moment from 'moment';
import adapters from '../core/core.adapters';
const FORMATS = {
datetime: 'MMM D, YYYY, h:mm:ss a',
millisecond: 'h:mm:ss.SSS a',
second: 'h:mm:ss a',
minute: 'h:mm a',
hour: 'hA',
day: 'MMM D',
week: 'll',
month: 'MMM YYYY',
quarter: '[Q]Q - YYYY',
year: 'YYYY'
};
adapters._date.override(typeof moment === 'function' ? {
_id: 'moment', // DEBUG ONLY
formats() {
return FORMATS;
},
parse(value, format) {
if (typeof value === 'string' && typeof format === 'string') {
value = moment(value, format);
} else if (!(value instanceof moment)) {
value = moment(value);
}
return value.isValid() ? value.valueOf() : null;
},
format(time, format) {
return moment(time).format(format);
},
add(time, amount, unit) {
return moment(time).add(amount, unit).valueOf();
},
diff(max, min, unit) {
return moment(max).diff(moment(min), unit);
},
startOf(time, unit, weekday) {
time = moment(time);
if (unit === 'isoWeek') {
return time.isoWeekday(weekday).valueOf();
}
return time.startOf(unit).valueOf();
},
endOf(time, unit) {
return moment(time).endOf(unit).valueOf();
}
} : {});

View File

@ -1,8 +0,0 @@
// -----------------------------------------------------------------------------
// IMPORTANT: do NOT submit new adapters to this repository, instead
// create an external library named `chartjs-adapter-{lib-name}`
// -----------------------------------------------------------------------------
// Built-in moment adapter that we need to keep for backward compatibility
// https://github.com/chartjs/Chart.js/issues/5542
import './adapter.moment';

View File

@ -45,9 +45,6 @@ Chart.Ticks = Ticks;
import * as scales from './scales/index'; import * as scales from './scales/index';
Object.keys(scales).forEach(key => Chart.scaleService.registerScale(scales[key])); Object.keys(scales).forEach(key => Chart.scaleService.registerScale(scales[key]));
// Load to register built-in adapters (as side effects)
import './adapters/index';
// Loading built-in plugins // Loading built-in plugins
import plugins from './plugins/index'; import plugins from './plugins/index';
for (const k in plugins) { for (const k in plugins) {

View File

@ -539,10 +539,10 @@ const defaultConfig = {
adapters: {}, adapters: {},
time: { time: {
parser: false, // false == a pattern string from https://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment parser: false, // false == a pattern string from or a custom callback that converts its argument to a timestamp
unit: false, // false == automatic or override with week, month, year, etc. unit: false, // false == automatic or override with week, month, year, etc.
round: false, // none, or override with week, month, year, etc. round: false, // none, or override with week, month, year, etc.
isoWeekday: false, // override week start day - see https://momentjs.com/docs/#/get-set/iso-weekday/ isoWeekday: false, // override week start day
minUnit: 'millisecond', minUnit: 'millisecond',
displayFormats: {} displayFormats: {}
}, },