diff --git a/CHANGELOG.md b/CHANGELOG.md index 0663bfb..8a607c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Changed +- Swaps out Moment.js for date-fns to improve blame annotation performance and to reduce the GitLen bundle size (saves ~400kb) ## [5.6.2] - 2017-10-11 ### Fixed diff --git a/package-lock.json b/package-lock.json index 1178c50..f1d937e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -375,6 +375,11 @@ } } }, + "date-fns": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" + }, "dateformat": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", @@ -1841,11 +1846,6 @@ } } }, - "moment": { - "version": "2.19.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.1.tgz", - "integrity": "sha1-VtoaLRy/AdOLfhr8McELz6GSkWc=" - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", diff --git a/package.json b/package.json index 2ee4b04..2635131 100644 --- a/package.json +++ b/package.json @@ -1998,13 +1998,13 @@ "dependencies": { "applicationinsights": "0.21.0", "copy-paste": "1.3.0", + "date-fns": "1.29.0", "iconv-lite": "0.4.19", "ignore": "3.3.5", "lodash.debounce": "4.0.8", "lodash.escaperegexp": "4.1.2", "lodash.isequal": "4.5.0", "lodash.once": "4.1.1", - "moment": "2.19.1", "spawn-rx": "2.0.12", "tmp": "0.0.33" }, diff --git a/src/system/date.ts b/src/system/date.ts index 730c996..a5f8124 100644 --- a/src/system/date.ts +++ b/src/system/date.ts @@ -1,9 +1,121 @@ 'use strict'; -import * as moment from 'moment'; +import { distanceInWordsToNow as _fromNow, format as _format } from 'date-fns'; +import * as en from 'date-fns/locale/en'; const MillisecondsPerMinute = 60000; // 60 * 1000 const MillisecondsPerDay = 86400000; // 24 * 60 * 60 * 1000 +// Taken from https://github.com/date-fns/date-fns/blob/601bc8e5708cbaebee5389bdaf51c2b4b33b73c4/src/locale/en/build_distance_in_words_locale/index.js +function buildDistanceInWordsLocale() { + const distanceInWordsLocale: { [key: string]: string | { one: string, other: string } } = { + lessThanXSeconds: { + one: 'less than a second', + other: 'less than {{count}} seconds' + }, + + xSeconds: { + one: '1 second', + other: '{{count}} seconds' + }, + + halfAMinute: 'half a minute', + + lessThanXMinutes: { + one: 'a few seconds', + other: 'less than {{count}} minutes' + }, + + xMinutes: { + one: 'a minute', + other: '{{count}} minutes' + }, + + aboutXHours: { + one: 'an hour', + other: '{{count}} hours' + }, + + xHours: { + one: 'an hour', + other: '{{count}} hours' + }, + + xDays: { + one: 'a day', + other: '{{count}} days' + }, + + aboutXMonths: { + one: 'a month', + other: '{{count}} months' + }, + + xMonths: { + one: 'a month', + other: '{{count}} months' + }, + + aboutXYears: { + one: 'a year', + other: '{{count}} years' + }, + + xYears: { + one: 'a year', + other: '{{count}} years' + }, + + overXYears: { + one: 'a year', + other: '{{count}} years' + }, + + almostXYears: { + one: 'a year', + other: '{{count}} years' + } + }; + + function localize(token: string, count: number, options: any) { + options = options || {}; + + const result = distanceInWordsLocale[token]; + + let value: string; + if (typeof result === 'string') { + value = result; + } + else { + if (count === 12 && token === 'xMonths') { + token = 'aboutXYears'; + count = 1; + } + + if (count === 1) { + value = result.one; + } + else { + value = result.other.replace('{{count}}', count.toString()); + } + } + + if (!options.addSuffix) return value; + + if (options.comparison > 0) return 'in ' + value; + + return value + ' ago'; + } + + return { + localize: localize + }; +} + +// Monkey patch the locale to customize the wording +(en as any).distanceInWords = buildDistanceInWordsLocale(); + +const formatterOptions = { addSuffix: true, locale: en }; + export namespace Dates { export interface IDateFormatter { @@ -28,6 +140,9 @@ export namespace Dates { } export function toFormatter(date: Date): IDateFormatter { - return moment(date); + return { + fromNow: () => _fromNow(date, formatterOptions), + format: (format: string) => _format(date, format) + }; } } \ No newline at end of file