Launch Week Day 5: Introducing Reachability for PHP.Learn More
Socket
Book a DemoSign in
Socket

javascript-time-ago

Package Overview
Dependencies
Maintainers
1
Versions
126
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

javascript-time-ago - npm Package Compare versions

Comparing version
0.2.3
to
0.2.4
+12
index.es6.js
import javascript_time_ago from './source/time ago'
// Add all locale data to `javascript-time-ago`.
// This module will be ignored when bundling
// for the browser with Browserify/Webpack.
global.javascript_time_ago = javascript_time_ago
require('./locales')
delete global.javascript_time_ago
// export { default, from_CLDR } from './source/time ago'
export default javascript_time_ago
export { a_day, days_in_a_month, days_in_a_year, gradation } from './source/classify elapsed'
'use strict'
var javascript_time_ago = require('./build/time ago')['default']
// Add all locale data to `javascript-time-ago`.
// This module will be ignored when bundling
// for the browser with Browserify/Webpack.
global.javascript_time_ago = javascript_time_ago
require('./locales')
delete global.javascript_time_ago
exports = module.exports = javascript_time_ago
exports['default'] = exports
var classify_elapsed = require('./build/classify elapsed')
exports.a_day = classify_elapsed.a_day
exports.days_in_a_month = classify_elapsed.days_in_a_month
exports.days_in_a_year = classify_elapsed.days_in_a_year
exports.gradation = classify_elapsed.gradation
var fs = require('fs')
fs.readdirSync('./locales').forEach(function(file)
{
var locale = file.replace(/\.js$/, '')
javascript_time_ago.locale(locale, require('./locales/' + locale))
})
+7
-3
{
"name": "javascript-time-ago",
"version": "0.2.3",
"version": "0.2.4",
"description": "International highly customizable relative time formatting",
"main": "build/index.js",
"jsnext:main": "source/index.js",
"main": "index.umd.js",
"jsnext:main": "index.es6.js",
"browser": {
"./locales": false,
"./locales.js": false
},
"peerDependencies": {

@@ -8,0 +12,0 @@ "intl-messageformat": "^1.3.0"

@@ -76,9 +76,9 @@ # javascript-time-ago

time_ago_english.format(new Date(Date.now() + 60 * 1000))
time_ago_english.format(new Date(Date.now() - 60 * 1000))
// "a minute ago"
time_ago_english.format(new Date(Date.now() + 2 * 60 * 60 * 1000))
time_ago_english.format(new Date(Date.now() - 2 * 60 * 60 * 1000))
// "2 hours ago"
time_ago_english.format(new Date(Date.now() + 24 * 60 * 60 * 1000))
time_ago_english.format(new Date(Date.now() - 24 * 60 * 60 * 1000))
// "yesterday"

@@ -91,9 +91,9 @@

time_ago_russian.format(new Date(Date.now() + 60 * 1000)))
time_ago_russian.format(new Date(Date.now() - 60 * 1000)))
// "минуту назад"
time_ago_russian.format(new Date(Date.now() + 2 * 60 * 60 * 1000)))
time_ago_russian.format(new Date(Date.now() - 2 * 60 * 60 * 1000)))
// "2 часа назад"
time_ago_russian.format(new Date(Date.now() + 24 * 60 * 60 * 1000))
time_ago_russian.format(new Date(Date.now() - 24 * 60 * 60 * 1000))
// "вчера"

@@ -125,6 +125,6 @@ ```

time_ago.format(new Date(Date.now() + 60 * 1000), twitter)
time_ago.format(new Date(Date.now() - 60 * 1000), twitter)
// "1m"
time_ago.format(new Date(Date.now() + 2 * 60 * 60 * 1000), twitter)
time_ago.format(new Date(Date.now() - 2 * 60 * 60 * 1000), twitter)
// "2h"

@@ -264,3 +264,3 @@ ```

const time_ago = new javascript_time_ago('ru')
time_ago.format(new Date(Date.now() + 60 * 1000))
time_ago.format(new Date(Date.now() - 60 * 1000))
// "1 минуту назад"

@@ -267,0 +267,0 @@ ```

{
"presets":
[
"react",
"es2015",
"stage-0"
],
"plugins":
[
"transform-runtime",
"add-module-exports",
"transform-react-display-name"
],
"env":
{
"development":
{
"plugins": []
},
"react-intl-extract-default-messages":
{
"plugins":
[
["react-intl",
{
"messagesDir": "./build/messages/",
"enforceDescriptions": true
}]
]
}
}
}
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _timeAgo = require('./time ago');
Object.defineProperty(exports, 'default', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_timeAgo).default;
}
});
Object.defineProperty(exports, 'from_CLDR', {
enumerable: true,
get: function get() {
return _timeAgo.from_CLDR;
}
});
var _classifyElapsed = require('./classify elapsed');
Object.defineProperty(exports, 'classify_elapsed', {
enumerable: true,
get: function get() {
return _interopRequireDefault(_classifyElapsed).default;
}
});
Object.defineProperty(exports, 'a_day', {
enumerable: true,
get: function get() {
return _classifyElapsed.a_day;
}
});
Object.defineProperty(exports, 'days_in_a_month', {
enumerable: true,
get: function get() {
return _classifyElapsed.days_in_a_month;
}
});
Object.defineProperty(exports, 'days_in_a_year', {
enumerable: true,
get: function get() {
return _classifyElapsed.days_in_a_year;
}
});
Object.defineProperty(exports, 'gradation', {
enumerable: true,
get: function get() {
return _classifyElapsed.gradation;
}
});
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
//# sourceMappingURL=index.js.map
{"version":3,"sources":["../source/index.js"],"names":[],"mappings":";;;;;;;;;;;4CAES;;;;;;oBAAS;;;;;;;;;oDACT;;;;;;4BAA6B;;;;;;4BAAO;;;;;;4BAAiB;;;;;;4BAAgB","file":"index.js","sourcesContent":["// just an npm package helper\n\nexport { default, from_CLDR, } from './time ago'\nexport { default as classify_elapsed, a_day, days_in_a_month, days_in_a_year, gradation } from './classify elapsed'"]}

Sorry, the diff of this file is not supported yet

// https://www.quora.com/What-is-the-average-number-of-days-in-a-month
export const days_in_a_month = 30.44
// "400 years have 146097 days (taking into account leap year rules)"
export const days_in_a_year = 146097 / 400
export const a_day = 24 * 60 * 60 // in seconds
export const gradation =
{
// just now
// 1 second ago
// …
// 59 seconds ago
// 1 minute ago
// …
// 59 minutes ago
// 1 hour ago
// …
// 24 hours ago
// 1 day ago
// …
// 7 days ago
// 1 week ago
// …
// 3 weeks ago
// 1 month ago
// …
// 11 months ago
// 1 year ago
// …
canonical: () =>
{
const result =
[
{
unit: 'just-now',
factor: 1
},
{
unit: 'second',
factor: 1,
threshold: 0.5
},
{
unit: 'minute',
factor: 60,
threshold: 59.5
},
{
unit: 'hour',
factor: 60 * 60,
threshold: 59.5 * 60
},
{
unit: 'day',
factor: a_day,
threshold: 23.5 * 60 * 60
},
{
unit: 'week',
factor: 7 * a_day,
threshold: 6.5 * a_day
},
{
unit: 'month',
factor: days_in_a_month * a_day,
threshold: 3.5 * 7 * a_day * a_day
},
{
unit: 'year',
factor: days_in_a_year * a_day,
threshold: 11.5 * days_in_a_month * a_day
}
]
return result
},
// just now
// 5 minutes ago
// 10 minutes ago
// 15 minutes ago
// 20 minutes ago
// half an hour ago
// an hour ago
// 2 hours ago
// …
// 20 hours ago
// yesterday
// 2 days ago
// 5 days ago
// a week ago
// 2 weeks ago
// 3 weeks ago
// a month ago
// 2 months ago
// 4 months ago
// half a year ago
// a year ago
// 2 years ago
// …
convenient: () =>
{
const result =
[
{
unit: 'just-now',
factor: 1
},
{
unit: 'second',
factor: 1,
threshold: 1
},
{
unit: 'minute',
factor: 60,
threshold: 45,
granularity: 5
},
{
unit: 'half-hour',
factor: 30 * 60,
threshold: 22.5 * 60
},
{
unit: 'hour',
factor: 60 * 60,
threshold: 42.5 * 60,
threshold_for_minute: 52.5 * 60
},
{
unit: 'day',
factor: a_day,
threshold: (20.5 / 24) * a_day
},
{
unit: 'week',
factor: 7 * a_day,
threshold: 5.5 * a_day
},
{
unit: 'month',
factor: days_in_a_month * a_day,
threshold: 3.5 * 7 * a_day
},
{
unit: 'half-year',
factor: 0.5 * days_in_a_year * a_day,
threshold: 4.5 * days_in_a_month * a_day
},
{
unit: 'year',
factor: days_in_a_year * a_day,
threshold: 9 * days_in_a_month * a_day,
threshold_for_month: 10.5 * days_in_a_month * a_day
}
]
return result
}
}
// Chooses the appropriate time measurement unit
// and also returns the corresponding rounded time amount.
//
// Rounds the `elapsed` time interval
// to the most appropriate time measurement unit.
//
// Parameters:
//
// elapsed - time interval (in seconds)
//
// units - a list of allowed time units
// (e.g. ['second', 'minute', 'hour', …])
//
// gradation - (optional) time scale gradation steps.
// (e.g.
// [
// { unit: 'second', factor: 1 },
// { unit: 'minute', factor: 60, threshold: 60 },
// …
// ])
//
// Returns an object of `unit` and `amount`
// (e.g. { unit: 'day', amount: 3 })
//
export default function classify_elapsed(elapsed, units, gradation_steps)
{
// Time interval measurement unit rounding gradation
gradation_steps = gradation_steps || gradation.convenient()
// Leave only supported gradation steps
gradation_steps = gradation_steps.filter(step => units.indexOf(step.unit) >= 0)
// Find the most appropriate time scale gradation step
let i = 0
while (i < gradation_steps.length)
{
// Current step of time scale
const step = gradation_steps[i]
// The next step of time scale
const next_step = i + 1 < gradation_steps.length ? gradation_steps[i + 1] : undefined
// If it's not the last step of time scale,
// and the next step of time scale is reachable,
// then proceed with that next step of time scale.
if (next_step)
{
// Allows threshold customization
// based on which time interval measurement units
// are available at the moment.
const specific_threshold = next_step[`threshold_for_${step.unit}`]
const next_step_threshold = specific_threshold || next_step.threshold
if (elapsed >= next_step_threshold)
{
i++
continue
}
}
// Either it's the last step of time scale,
// or the next step of time scale is unreachable,
// so stick with the current step of time scale.
const exact_amount = elapsed / step.factor
let amount = Math.round(exact_amount)
// Amount shouldn't be zero,
// so set it to 1 at least.
if (amount === 0)
{
amount = elapsed >= 0 ? 1 : -1
}
// Apply granularity to the time amount
// (and fallback to the previous step
// if the first level of granularity
// isn't met by this amount)
if (step.granularity)
{
// Recalculate time amount based on the granularity
const remainder = exact_amount % step.granularity
amount = exact_amount - remainder
amount += Math.round(remainder / step.granularity) * step.granularity
// If the granularity for this step of time scale
// is too high, then fallback
// to the previous step of time scale.
// (if there is the previous step of time scale)
if (amount === 0)
{
const previous_step = gradation_steps[i - 1]
if (previous_step)
{
const previous_step_result =
{
unit : previous_step.unit,
amount : Math.round(elapsed / previous_step.factor)
}
return previous_step_result
}
}
}
// Result
return { unit: step.unit, amount }
}
throw new Error(`Not a single time unit of "${units.join(', ')}" was specified `
+ `in the gradation \n ${JSON.stringify({ gradation: gradation_steps }, null, 3)}`)
}
// just an npm package helper
export { default, from_CLDR, } from './time ago'
export { default as classify_elapsed, a_day, days_in_a_month, days_in_a_year, gradation } from './classify elapsed'
import { resolve_locale } from './time ago'
import { gradation, a_day } from './classify elapsed'
const twitter_formatters = {}
export default function(locales)
{
const styles =
{
// Twitter style relative time.
// Seconds, minutes and hours are shown relatively,
// and other intervals can be shown using full date format.
twitter()
{
const locale = resolve_locale(locales)
if (!twitter_formatters[locale])
{
twitter_formatters[locale] =
{
// "Apr 11" (MMMd)
same_year : new Intl.DateTimeFormat(locale, { month: 'short', day: 'numeric' }),
// "Apr 11, 2017" (yMMMd)
another_year : new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'short', day: 'numeric' })
}
}
const twitter_same_year_date_formatter = twitter_formatters[locale].same_year
const twitter_another_year_date_formatter = twitter_formatters[locale].another_year
const twitter_gradation = gradation.canonical()
for (let step of twitter_gradation)
{
if (step.unit === 'minute')
{
step.threshold = 45
break
}
}
const options =
{
// Twitter style relative time.
// Seconds, minutes and hours are shown relatively,
// and other intervals can be shown using full date format.
override({ elapsed, time, date, now })
{
// If less than 24 hours elapsed,
// then format it relatively.
if (Math.abs(elapsed) < a_day - 30 * 60)
{
return
}
// If `date` and `now` happened the same year,
// then show month and day
if (new Date(now).getFullYear() === date.getFullYear())
{
return twitter_same_year_date_formatter.format(date, 'MMMd')
}
// If `date` and `now` happened in defferent years,
// then show full date
return twitter_another_year_date_formatter.format(date, 'yMMMd')
},
units: ['just-now', 'minute', 'hour'],
gradation: twitter_gradation,
flavour: 'tiny'
}
return options
},
// I prefer this one.
//
// just now
// 5 minutes
// 10 minutes
// 15 minutes
// 20 minutes
// half an hour
// an hour
// 2 hours
// …
// 20 hours
// yesterday
// 2 days
// a week
// 2 weeks
// 3 weeks
// a month
// 2 months
// 3 months
// 4 months
// half a year
// a year
// 2 years
//
fuzzy()
{
const options =
{
gradation: gradation.convenient(),
flavour: 'long_concise',
units: ['just-now', 'minute', 'half-hour', 'hour', 'day', 'week', 'month', 'half-year', 'year']
}
return options
}
}
return styles
}
// a part of this code is adopted from
// https://github.com/yahoo/intl-relativeformat/
import IntlMessageFormat from 'intl-messageformat'
import classify_elapsed from './classify elapsed'
import style from './style'
export default class React_time_ago
{
// Fallback locale
// (when not a single supplied preferred locale is available)
static default_locale = 'en'
// For all configured locales
// their relative time formatter messages will be stored here
static locale_data = {}
// Relative time interval message formatters cache
formatters = {}
constructor(locales, options)
{
// Make a copy of `locales` if it's an array, so that it doesn't change
// since it's used lazily.
if (Array.isArray(locales))
{
locales = locales.concat()
}
// Choose the most appropriate locale
this.locale = resolve_locale(locales)
// Is passed later on to `IntlMessageFormat`
this.locales = locales
// Presets
this.style = style(locales)
}
// Formats the relative date.
//
// Returns: a string
//
// Parameters:
//
// options - (optional)
//
// units - a list of allowed time units
// (e.g. ['second', 'minute', 'hour', …])
//
// gradation - time scale gradation steps.
// (e.g.
// [
// { unit: 'second', factor: 1 },
// { unit: 'minute', factor: 60, threshold: 60 },
// …
// ])
//
// override - function ({ elapsed, time, date, now })
//
// If the `override` function returns a value,
// then the `.format()` call will return that value.
// Otherwise it has no effect.
//
format(input, options = {})
{
// Get locale messages for this formatting flavour
const { flavour, locale_data } = this.locale_data(options.flavour)
let date
let time
if (typeof input === 'number')
{
time = input
date = new Date(input)
}
else if (input.constructor === Date)
{
date = input
time = input.getTime()
}
else
{
throw new Error(`Unsupported fuzzy time input: ${typeof input}, ${input}`)
}
// can pass a custom `now` for testing purpose
const now = options.now || Date.now()
// how much time elapsed (in seconds)
const elapsed = (now - time) / 1000 // in seconds
// Allows output customization.
// For example, seconds, minutes and hours can be shown relatively,
// and other intervals can be shown using full date format.
// (see Twitter style)
if (options.override)
{
const override = options.override({ elapsed, time, date, now })
if (override !== undefined)
{
return override
}
}
// Available time interval measurement units
let units = Object.keys(locale_data)
if (options.units)
{
// Find available time interval measurement units
units = options.units.filter(unit => units.indexOf(unit) >= 0)
}
// Choose the appropriate time measurement unit
// and get the corresponding rounded time amount
const { unit, amount } = classify_elapsed(Math.abs(elapsed), units, options.gradation)
// If no time unit is suitable, just output empty string
if (!unit)
{
return ''
}
// format the message for the chosen time measurement unit
// (second, minute, hour, day, etc)
const formatters = this.get_formatters(unit, flavour)
// default formatter: "X units"
let formatter = formatters.default
// in case of "0 units"
if (amount === 0 && formatters.current)
{
formatter = formatters.current
}
// in case of "previous unit" or "next unit"
if ((amount === -1 || amount === 1) && formatters.previous_next)
{
formatter = formatters.previous_next
}
// return formatted time amount
return formatter.format
({
'0' : amount,
when : elapsed >= 0 ? 'past' : 'future'
})
}
// Gets locale messages for this formatting flavour
locale_data(flavour)
{
// Get relative time formatter messages for this locale
const locale_data = React_time_ago.locale_data[this.locale]
// Fallback to "default" flavour if the given flavour isn't available
if (!flavour || !locale_data[flavour])
{
flavour = 'default'
}
return { flavour, locale_data: locale_data[flavour] }
}
// lazy creation of a formatter for a given time measurement unit
// (second, minute, hour, day, etc)
get_formatters(unit, flavour)
{
if (!this.formatters[flavour])
{
this.formatters[flavour] = {}
}
const formatters = this.formatters[flavour]
// Create a new synthetic message based on the locale data from CLDR.
if (!formatters[unit])
{
formatters[unit] = this.compile_formatters(unit, flavour)
}
return formatters[unit]
}
// compiles formatter for the specified time measurement unit
// (second, minute, hour, day, etc)
compile_formatters(unit, flavour)
{
// Locale specific time interval formatter messages
// for the given time interval measurement unit
const formatter_messages = React_time_ago.locale_data[this.locale][flavour][unit]
// Locale specific time interval formatter messages
// for the given time interval measurement unit
// for "past" and "future"
//
// (e.g.
// {
// "relativeTimePattern-count-one": "{0} second ago",
// "relativeTimePattern-count-other": "{0} seconds ago"
// })
//
const past_formatter_messages = formatter_messages.past
const future_formatter_messages = formatter_messages.future
// `format.js` number formatter messages
// e.g. "one {# second ago} other {# seconds ago}"
let past_formatter = ''
let future_formatter = ''
// Compose "past" formatter specification
// (replacing CLDR number placeholder "{0}"
// with format.js number placeholder "#")
for (let key of Object.keys(past_formatter_messages))
{
past_formatter += ` ${key}
{${past_formatter_messages[key].replace('{0}', '#')}}`
}
// Compose "future" formatter specification
// (replacing CLDR number placeholder "{0}"
// with format.js number placeholder "#")
for (let key of Object.keys(future_formatter_messages))
{
// e.g. += " one {# sec. ago}"
future_formatter += ` ${key}
{${future_formatter_messages[key].replace('{0}', '#')}}`
}
// The ultimate time interval `format.js` specification
// ("0" will be replaced with the first argument
// when the message will be formatted)
const message = `{ when, select, past {{0, plural, ${past_formatter}}}
future {{0, plural, ${future_formatter}}} }`
// Create the synthetic IntlMessageFormat instance
// using the original locales specified by the user
const default_formatter = new IntlMessageFormat(message, this.locales)
const formatters =
{
default: default_formatter
}
// "0 units" formatter
if (formatter_messages.current)
{
formatters.current =
{
format: () => formatter_messages.current
}
}
// "previous unit" and "next unit" formatter
if (formatter_messages.previous && formatter_messages.next)
{
const previous_next_message = `{ when, select, past {${formatter_messages.previous}}
future {${formatter_messages.next}} }`
// Create the synthetic IntlMessageFormat instance
// using the original locales specified by the user
formatters.previous_next = new IntlMessageFormat(previous_next_message, this.locales)
}
return formatters
}
}
// Chooses the most appropriate locale
// based on the list of preferred locales supplied by the user
export function resolve_locale(locales)
{
// Suppose it's an array
if (typeof locales === 'string')
{
locales = [locales]
}
// Create a copy of the array so we can push on the default locale.
locales = (locales || []).concat(React_time_ago.default_locale)
// Using the set of locales + the default locale, we look for the first one
// which that has been registered. When data does not exist for a locale, we
// traverse its ancestors to find something that's been registered within
// its hierarchy of locales. Since we lack the proper `parentLocale` data
// here, we must take a naive approach to traversal.
for (let locale of locales)
{
const locale_parts = locale.toLowerCase().split('-')
while (locale_parts.length)
{
const locale_try = locale_parts.join('-')
if (React_time_ago.locale_data[locale_try])
{
// Return the normalized locale string;
// e.g., we return "en-US",
// instead of "en-us".
return locale_try
}
locale_parts.pop()
}
}
throw new Error(`No locale data has been added for any of the locales: ${locales.join(', ')}`)
}
// Adds locale data
React_time_ago.locale = function(locale, locale_data)
{
const locale_data_map = {}
// Supports multiple locale variations
// (e.g. "default", "short", "normal", "long", etc)
if (!locale_data.default)
{
// Convert from CLDR format (if needed)
locale_data_map.default = from_CLDR(locale_data)
}
else
{
for (let key of Object.keys(locale_data))
{
// Convert from CLDR format (if needed)
locale_data_map[key] = from_CLDR(locale_data[key])
}
}
// Store locale specific messages in the static variable
React_time_ago.locale_data[locale.toLowerCase()] = locale_data_map
// (will be added manually by this library user)
// // Add locale data to IntlMessageFormat
// // (to be more specific: the `pluralRuleFunction`)
// require('intl-messageformat/locale-data/ru')
}
// Converts locale data from CLDR format (if needed)
export function from_CLDR(data)
{
const converted = {}
for (let key of Object.keys(data))
{
const entry = data[key]
const converted_entry = {}
if (entry.previous)
{
converted_entry.previous = entry.previous
}
if (entry.current)
{
converted_entry.current = entry.current
}
if (entry.next)
{
converted_entry.next = entry.next
}
if (entry.past)
{
converted_entry.past = entry.past
}
if (entry.future)
{
converted_entry.future = entry.future
}
converted[key] = converted_entry
if (entry['relative-type--1'])
{
converted_entry.previous = entry['relative-type--1']
}
if (entry['relative-type-0'])
{
converted_entry.current = entry['relative-type-0']
}
if (entry['relative-type-1'])
{
converted_entry.next = entry['relative-type-1']
}
if (entry['relativeTime-type-past'])
{
const past = entry['relativeTime-type-past']
converted_entry.past = {}
for (let subkey of Object.keys(past))
{
const prefix = 'relativeTimePattern-count-'
const converted_subkey = subkey.replace(prefix, '')
converted_entry.past[converted_subkey] = past[subkey]
}
}
if (entry['relativeTime-type-future'])
{
const future = entry['relativeTime-type-future']
converted_entry.future = {}
for (let subkey of Object.keys(future))
{
const prefix = 'relativeTimePattern-count-'
const converted_subkey = subkey.replace(prefix, '')
converted_entry.future[converted_subkey] = future[subkey]
}
}
}
return converted
}
export const long = {
"year": {
"displayName": "year",
"relative-type--1": "a year ago",
"relative-type-0": "this year",
"relative-type-1": "in a year",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} year",
"relativeTimePattern-count-other": "in {0} years"
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} year ago",
"relativeTimePattern-count-other": "{0} years ago"
}
},
"half-year": {
"displayName": "half a year",
"relativeTime-type-future": {
"relativeTimePattern-count-other": "in half a year"
},
"relativeTime-type-past": {
"relativeTimePattern-count-other": "half a year ago"
}
},
"month": {
"displayName": "month",
"relative-type--1": "a month ago",
"relative-type-0": "this month",
"relative-type-1": "in a month",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} month",
"relativeTimePattern-count-other": "in {0} months"
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} month ago",
"relativeTimePattern-count-other": "{0} months ago"
}
},
"week": {
"displayName": "week",
"relative-type--1": "a week ago",
"relative-type-0": "this week",
"relative-type-1": "in a week",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} week",
"relativeTimePattern-count-other": "in {0} weeks"
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} week ago",
"relativeTimePattern-count-other": "{0} weeks ago"
}
},
"day": {
"displayName": "day",
"relative-type--1": "yesterday",
"relative-type-0": "today",
"relative-type-1": "tomorrow",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} day",
"relativeTimePattern-count-other": "in {0} days"
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} day ago",
"relativeTimePattern-count-other": "{0} days ago"
}
},
"hour": {
"displayName": "hour",
"relative-type--1": "an hour ago",
"relative-type-0": "this hour",
"relative-type-1": "in an hour",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} hour",
"relativeTimePattern-count-other": "in {0} hours"
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} hour ago",
"relativeTimePattern-count-other": "{0} hours ago"
}
},
"half-hour": {
"displayName": "half an hour",
"relativeTime-type-future": {
"relativeTimePattern-count-other": "in half an hour"
},
"relativeTime-type-past": {
"relativeTimePattern-count-other": "half an hour ago"
}
},
"minute": {
"displayName": "minute",
"relative-type--1": "a minute ago",
"relative-type-0": "this minute",
"relative-type-1": "in a minute",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} minute",
"relativeTimePattern-count-other": "in {0} minutes"
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} minute ago",
"relativeTimePattern-count-other": "{0} minutes ago"
}
},
"second": {
"displayName": "second",
"relative-type-0": "now",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} second",
"relativeTimePattern-count-other": "in {0} seconds"
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} second ago",
"relativeTimePattern-count-other": "{0} seconds ago"
}
},
"just-now": {
"displayName": "just now",
"relativeTime-type-future": {
"relativeTimePattern-count-other": "in a moment"
},
"relativeTime-type-past": {
"relativeTimePattern-count-other": "just now"
}
}
}
export const short = {
"year": {
"displayName": "yr.",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} yr.",
"relativeTimePattern-count-other": "in {0} yr."
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} yr. ago",
"relativeTimePattern-count-other": "{0} yr. ago"
}
},
"month": {
"displayName": "mo.",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} mo.",
"relativeTimePattern-count-other": "in {0} mo."
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} mo. ago",
"relativeTimePattern-count-other": "{0} mo. ago"
}
},
"week": {
"displayName": "wk.",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} wk.",
"relativeTimePattern-count-other": "in {0} wk."
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} wk. ago",
"relativeTimePattern-count-other": "{0} wk. ago"
}
},
"day": {
"displayName": "day",
"relative-type--1": "yesterday",
"relative-type-0": "today",
"relative-type-1": "tomorrow",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} day",
"relativeTimePattern-count-other": "in {0} days"
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} day ago",
"relativeTimePattern-count-other": "{0} days ago"
}
},
"hour": {
"displayName": "hr.",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} hr.",
"relativeTimePattern-count-other": "in {0} hr."
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} hr. ago",
"relativeTimePattern-count-other": "{0} hr. ago"
}
},
"minute": {
"displayName": "min.",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} min.",
"relativeTimePattern-count-other": "in {0} min."
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} min. ago",
"relativeTimePattern-count-other": "{0} min. ago"
}
},
"second": {
"displayName": "sec.",
"relative-type-0": "now",
"relativeTime-type-future": {
"relativeTimePattern-count-one": "in {0} sec.",
"relativeTimePattern-count-other": "in {0} sec."
},
"relativeTime-type-past": {
"relativeTimePattern-count-one": "{0} sec. ago",
"relativeTimePattern-count-other": "{0} sec. ago"
}
},
"just-now": {
"displayName": "just now",
"relativeTime-type-future": {
"relativeTimePattern-count-other": "now"
},
"relativeTime-type-past": {
"relativeTimePattern-count-other": "now"
}
}
}
export default long
import are_intl_locales_supported from 'intl-locales-supported'
if (global.Intl)
{
// Determine if the built-in `Intl` has the locale data we need
if (!are_intl_locales_supported(['en', 'ru']))
{
// `Intl` exists, but it doesn't have the data we need, so load the
// polyfill and patch the constructors we need with the polyfill's
const Intl_polyfill = require('intl')
Intl.NumberFormat = Intl_polyfill.NumberFormat
Intl.DateTimeFormat = Intl_polyfill.DateTimeFormat
}
}
else
{
// No `Intl`, so use and load the polyfill
global.Intl = require('intl')
}
import chai from 'chai'
chai.should()
require('./time ago')
// import chai from 'chai'
// chai.should()
// import javascript_time_ago from '../source/time ago'
import javascript_time_ago, { a_day, days_in_a_month, days_in_a_year, from_CLDR, gradation } from '../source'
// Load locale specific relative date/time messages
import { short as english_short_cldr, long as english_long_cldr } from './locales/en-cldr'
import english, { short as english_short, long as english_long, tiny as english_tiny } from '../locales/en'
import russian, { short as russian_short, long as russian_long, tiny as russian_tiny } from '../locales/ru'
// Load number pluralization functions for the locales.
// (the ones that decide if a number is gonna be
// "zero", "one", "two", "few", "many" or "other")
// http://cldr.unicode.org/index/cldr-spec/plural-rules
// https://github.com/eemeli/make-plural.js
//
global.IntlMessageFormat = require('intl-messageformat')
require('intl-messageformat/dist/locale-data/en')
require('intl-messageformat/dist/locale-data/ru')
delete global.IntlMessageFormat
describe(`time ago`, function()
{
beforeEach(function()
{
// Set locale specific relative date/time messages
javascript_time_ago.locale('en', english_long)
javascript_time_ago.locale('ru', russian_long)
})
afterEach(function()
{
//
})
it(`should convert from Unicode CLDR`, function()
{
from_CLDR(english_short_cldr).should.deep.equal(english_short)
from_CLDR(english_long_cldr).should.deep.equal(english_long)
})
// it(`should omit just now`, function()
// {
// javascript_time_ago.locale('en', english_short)
//
// const time_ago = new javascript_time_ago('en')
//
// const custom_gradation = gradation.convenient()
// while (custom_gradation[0].unit !== 'minute')
// {
// custom_gradation.shift()
// }
//
// const now = Date.now()
// const elapsed = time => time_ago.format(now - time * 1000, { now, gradation: custom_gradation })
//
// elapsed(0 ).should.equal('')
// elapsed(2.49 * 60).should.equal('')
// elapsed(2.51 * 60).should.equal('5 min. ago')
// })
it(`should format Twitter style relative time (English)`, function()
{
javascript_time_ago.locale('en', english_tiny)
const time_ago = new javascript_time_ago('en')
const twitter_style = time_ago.style.twitter()
const now = new Date(2016, 3, 10, 22, 59).getTime()
const elapsed = time => time_ago.format(now - time * 1000, { now, ...twitter_style })
elapsed(0).should.equal('')
elapsed(44.9).should.equal('')
elapsed(45.1).should.equal('1m')
elapsed(1.49 * 60).should.equal('1m')
elapsed(1.51 * 60).should.equal('2m')
elapsed(2.49 * 60).should.equal('2m')
elapsed(2.51 * 60).should.equal('3m')
// …
elapsed(59.49 * 60).should.equal('59m')
elapsed(59.51 * 60).should.equal('1h')
elapsed(1.49 * 60 * 60).should.equal('1h')
elapsed(1.51 * 60 * 60).should.equal('2h')
elapsed(2.49 * 60 * 60).should.equal('2h')
elapsed(2.51 * 60 * 60).should.equal('3h')
// …
elapsed(23.49 * 60 * 60).should.equal('23h')
elapsed(a_day + 62 * 60).should.equal('Apr 9')
// …
elapsed(days_in_a_year * a_day).should.equal('Apr 11, 2015')
})
it(`should format Twitter style relative time (Russian)`, function()
{
javascript_time_ago.locale('ru', russian)
const time_ago = new javascript_time_ago(['ru'])
const twitter_style = time_ago.style.twitter()
const now = new Date(2016, 3, 10, 22, 59).getTime()
const elapsed = time => time_ago.format(now - time * 1000, { now, ...twitter_style })
elapsed(0).should.equal('')
elapsed(44.9).should.equal('')
elapsed(45.1).should.equal('1м')
elapsed(1.49 * 60).should.equal('1м')
elapsed(1.51 * 60).should.equal('2м')
elapsed(2.49 * 60).should.equal('2м')
elapsed(2.51 * 60).should.equal('3м')
// …
elapsed(59.49 * 60).should.equal('59м')
elapsed(59.51 * 60).should.equal('1ч')
elapsed(1.49 * 60 * 60).should.equal('1ч')
elapsed(1.51 * 60 * 60).should.equal('2ч')
elapsed(2.49 * 60 * 60).should.equal('2ч')
elapsed(2.51 * 60 * 60).should.equal('3ч')
// …
elapsed(23.49 * 60 * 60).should.equal('23ч')
elapsed(a_day + 62 * 60).should.equal('9 апр.')
// …
elapsed(days_in_a_year * a_day).should.equal('11 апр. 2015 г.')
})
it(`should format fuzzy style relative time (English)`, function()
{
javascript_time_ago.locale('en', english)
const time_ago = new javascript_time_ago('en-US')
convenient_gradation_test
([
'just now',
'5 minutes',
'10 minutes',
'15 minutes',
'20 minutes',
'half an hour',
'half an hour',
'half an hour',
'half an hour',
'an hour',
'an hour',
'an hour',
'2 hours',
'3 hours',
'4 hours',
'5 hours',
'6 hours',
'7 hours',
'8 hours',
'9 hours',
'10 hours',
'11 hours',
'12 hours',
'13 hours',
'14 hours',
'15 hours',
'16 hours',
'17 hours',
'18 hours',
'19 hours',
'20 hours',
'yesterday',
'2 days',
'3 days',
'4 days',
'5 days',
'a week',
'2 weeks',
'3 weeks',
'a month',
'2 months',
'3 months',
'4 months',
'half a year',
'half a year',
'half a year',
'half a year',
'half a year',
'a year',
'a year',
'a year',
'2 years',
'3 years',
'100 years'
],
time_ago,
time_ago.style.fuzzy())
})
it(`should format fuzzy style relative time (Russian)`, function()
{
javascript_time_ago.locale('ru', russian)
const time_ago = new javascript_time_ago('ru-RU')
convenient_gradation_test
([
'только что',
'5 минут',
'10 минут',
'15 минут',
'20 минут',
'полчаса',
'полчаса',
'полчаса',
'полчаса',
'час',
'час',
'час',
'2 часа',
'3 часа',
'4 часа',
'5 часов',
'6 часов',
'7 часов',
'8 часов',
'9 часов',
'10 часов',
'11 часов',
'12 часов',
'13 часов',
'14 часов',
'15 часов',
'16 часов',
'17 часов',
'18 часов',
'19 часов',
'20 часов',
'вчера',
'2 дня',
'3 дня',
'4 дня',
'5 дней',
'неделю',
'2 недели',
'3 недели',
'месяц',
'2 месяца',
'3 месяца',
'4 месяца',
'полгода',
'полгода',
'полгода',
'полгода',
'полгода',
'год',
'год',
'год',
'2 года',
'3 года',
'100 лет'
],
time_ago,
time_ago.style.fuzzy())
})
it(`should reduce locale to language code`, function()
{
javascript_time_ago.locale('ru', russian_tiny)
const time_ago = new javascript_time_ago(['ru-RU'])
const twitter_style = time_ago.style.twitter()
const now = Date.now()
const elapsed = time => time_ago.format(now - time * 1000, { now })
elapsed(45.1).should.equal('45с')
elapsed(45.1 * 60).should.equal('45м')
})
it(`should format time correctly for English language (short)`, function()
{
const units = ['just-now', 'minute', 'half-hour', 'hour', 'day', 'week', 'month', 'half-year', 'year']
javascript_time_ago.locale('en', english_short)
convenient_gradation_test
([
'now',
'5 min. ago',
'10 min. ago',
'15 min. ago',
'20 min. ago',
'25 min. ago',
'30 min. ago',
'35 min. ago',
'40 min. ago',
'45 min. ago',
'50 min. ago',
'1 hr. ago',
'2 hr. ago',
'3 hr. ago',
'4 hr. ago',
'5 hr. ago',
'6 hr. ago',
'7 hr. ago',
'8 hr. ago',
'9 hr. ago',
'10 hr. ago',
'11 hr. ago',
'12 hr. ago',
'13 hr. ago',
'14 hr. ago',
'15 hr. ago',
'16 hr. ago',
'17 hr. ago',
'18 hr. ago',
'19 hr. ago',
'20 hr. ago',
'yesterday',
'2 days ago',
'3 days ago',
'4 days ago',
'5 days ago',
'1 wk. ago',
'2 wk. ago',
'3 wk. ago',
'1 mo. ago',
'2 mo. ago',
'3 mo. ago',
'4 mo. ago',
'5 mo. ago',
'6 mo. ago',
'7 mo. ago',
'8 mo. ago',
'9 mo. ago',
'9 mo. ago',
'10 mo. ago',
'1 yr. ago',
'2 yr. ago',
'3 yr. ago',
'100 yr. ago'
],
new javascript_time_ago('en'),
{ units })
})
it(`should format time correctly for English language (long)`, function()
{
const units = ['just-now', 'minute', 'half-hour', 'hour', 'day', 'week', 'month', 'half-year', 'year']
javascript_time_ago.locale('en', english_long)
convenient_gradation_test
([
'just now',
'5 minutes ago',
'10 minutes ago',
'15 minutes ago',
'20 minutes ago',
'half an hour ago',
'half an hour ago',
'half an hour ago',
'half an hour ago',
'an hour ago',
'an hour ago',
'an hour ago',
'2 hours ago',
'3 hours ago',
'4 hours ago',
'5 hours ago',
'6 hours ago',
'7 hours ago',
'8 hours ago',
'9 hours ago',
'10 hours ago',
'11 hours ago',
'12 hours ago',
'13 hours ago',
'14 hours ago',
'15 hours ago',
'16 hours ago',
'17 hours ago',
'18 hours ago',
'19 hours ago',
'20 hours ago',
'yesterday',
'2 days ago',
'3 days ago',
'4 days ago',
'5 days ago',
'a week ago',
'2 weeks ago',
'3 weeks ago',
'a month ago',
'2 months ago',
'3 months ago',
'4 months ago',
'half a year ago',
'half a year ago',
'half a year ago',
'half a year ago',
'half a year ago',
'a year ago',
'a year ago',
'a year ago',
'2 years ago',
'3 years ago',
'100 years ago'
],
new javascript_time_ago('en'),
{ units })
})
it(`should format time correctly for Russian language (short)`, function()
{
const units = ['just-now', 'minute', 'half-hour', 'hour', 'day', 'week', 'month', 'half-year', 'year']
javascript_time_ago.locale('ru', russian_short)
convenient_gradation_test
([
'только что',
'5 мин. назад',
'10 мин. назад',
'15 мин. назад',
'20 мин. назад',
'25 мин. назад',
'30 мин. назад',
'35 мин. назад',
'40 мин. назад',
'45 мин. назад',
'50 мин. назад',
'1 ч. назад',
'2 ч. назад',
'3 ч. назад',
'4 ч. назад',
'5 ч. назад',
'6 ч. назад',
'7 ч. назад',
'8 ч. назад',
'9 ч. назад',
'10 ч. назад',
'11 ч. назад',
'12 ч. назад',
'13 ч. назад',
'14 ч. назад',
'15 ч. назад',
'16 ч. назад',
'17 ч. назад',
'18 ч. назад',
'19 ч. назад',
'20 ч. назад',
'вчера',
'2 д. назад',
'3 д. назад',
'4 д. назад',
'5 д. назад',
'1 нед. назад',
'2 нед. назад',
'3 нед. назад',
'1 мес. назад',
'2 мес. назад',
'3 мес. назад',
'4 мес. назад',
'5 мес. назад',
'6 мес. назад',
'7 мес. назад',
'8 мес. назад',
'9 мес. назад',
'9 мес. назад',
'10 мес. назад',
'1 г. назад',
'2 г. назад',
'3 г. назад',
'100 л. назад'
],
new javascript_time_ago('ru'),
{ units })
})
it(`should format time correctly for Russian language (long)`, function()
{
const units = ['just-now', 'minute', 'half-hour', 'hour', 'day', 'week', 'month', 'half-year', 'year']
javascript_time_ago.locale('ru', russian_long)
convenient_gradation_test
([
'только что',
'5 минут назад',
'10 минут назад',
'15 минут назад',
'20 минут назад',
'полчаса назад',
'полчаса назад',
'полчаса назад',
'полчаса назад',
'час назад',
'час назад',
'час назад',
'2 часа назад',
'3 часа назад',
'4 часа назад',
'5 часов назад',
'6 часов назад',
'7 часов назад',
'8 часов назад',
'9 часов назад',
'10 часов назад',
'11 часов назад',
'12 часов назад',
'13 часов назад',
'14 часов назад',
'15 часов назад',
'16 часов назад',
'17 часов назад',
'18 часов назад',
'19 часов назад',
'20 часов назад',
'вчера',
'2 дня назад',
'3 дня назад',
'4 дня назад',
'5 дней назад',
'неделю назад',
'2 недели назад',
'3 недели назад',
'месяц назад',
'2 месяца назад',
'3 месяца назад',
'4 месяца назад',
'полгода назад',
'полгода назад',
'полгода назад',
'полгода назад',
'полгода назад',
'год назад',
'год назад',
'год назад',
'2 года назад',
'3 года назад',
'100 лет назад'
],
new javascript_time_ago('ru'),
{ units })
})
})
function convenient_gradation_test(convenient_gradation_labels, time_ago, options = {})
{
const now = Date.now()
const elapsed = time => time_ago.format(now - time * 1000, { now, ...options })
if (convenient_gradation.length !== convenient_gradation_labels.length)
{
throw new Error(`Array length mismatch. Gradation steps: ${convenient_gradation.length}, labels: ${convenient_gradation_labels.length}`)
}
let i = 0
while (i < convenient_gradation.length)
{
for (let time of convenient_gradation[i])
{
elapsed(time).should.equal(convenient_gradation_labels[i])
}
i++
}
}
const convenient_gradation =
[
// 'just now':
[
0,
2.49 * 60
],
// '5 minutes ago':
[
2.51 * 60,
7.49 * 60
],
// '10 minutes ago':
[
7.51 * 60,
12.49 * 60
],
// '15 minutes ago':
[
12.51 * 60,
17.49 * 60
],
// '20 minutes ago':
[
17.51 * 60,
22.49 * 60
],
// '25 minutes ago':
[
22.51 * 60,
27.49 * 60
],
// '30 minutes ago':
[
27.51 * 60,
32.49 * 60
],
// '35 minutes ago':
[
32.51 * 60,
37.49 * 60
],
// '40 minutes ago':
[
37.51 * 60,
42.49 * 60
],
// '45 minutes ago':
[
42.51 * 60,
47.49 * 60
],
// '50 minutes ago':
[
47.51 * 60,
52.49 * 60
],
// 'an hour ago':
[
55.01 * 60,
1.49 * 60 * 60
],
// '2 hours ago':
[
1.51 * 60 * 60,
2.49 * 60 * 60
],
// '3 hours ago':
[
2.51 * 60 * 60,
3.49 * 60 * 60
],
// '4 hours ago':
[
3.51 * 60 * 60,
4.49 * 60 * 60
],
// '5 hours ago':
[
4.51 * 60 * 60,
5.49 * 60 * 60
],
// '6 hours ago':
[
5.51 * 60 * 60,
6.49 * 60 * 60
],
// '7 hours ago':
[
6.51 * 60 * 60,
7.49 * 60 * 60
],
// '8 hours ago':
[
7.51 * 60 * 60,
8.49 * 60 * 60
],
// '9 hours ago':
[
8.51 * 60 * 60,
9.49 * 60 * 60
],
// '10 hours ago':
[
9.51 * 60 * 60,
10.49 * 60 * 60
],
// '11 hours ago':
[
10.51 * 60 * 60,
11.49 * 60 * 60
],
// '12 hours ago':
[
11.51 * 60 * 60,
12.49 * 60 * 60
],
// '13 hours ago':
[
12.51 * 60 * 60,
13.49 * 60 * 60
],
// '14 hours ago':
[
13.51 * 60 * 60,
14.49 * 60 * 60
],
// '15 hours ago':
[
14.51 * 60 * 60,
15.49 * 60 * 60
],
// '16 hours ago':
[
15.51 * 60 * 60,
16.49 * 60 * 60
],
// '17 hours ago':
[
16.51 * 60 * 60,
17.49 * 60 * 60
],
// '18 hours ago':
[
17.51 * 60 * 60,
18.49 * 60 * 60
],
// '19 hours ago':
[
18.51 * 60 * 60,
19.49 * 60 * 60
],
// '20 hours ago':
[
19.51 * 60 * 60,
20.49 * 60 * 60
],
// 'yesterday':
[
20.51 * 60 * 60,
1.49 * a_day
],
// '2 days ago':
[
1.51 * a_day,
2.49 * a_day
],
// '3 days ago':
[
2.51 * a_day,
3.49 * a_day
],
// '4 days ago':
[
3.51 * a_day,
4.49 * a_day
],
// '5 days ago':
[
4.51 * a_day,
5.49 * a_day
],
// 'a week ago':
[
5.51 * a_day,
1.49 * 7 * a_day
],
// '2 weeks ago':
[
1.51 * 7 * a_day,
2.49 * 7 * a_day
],
// '3 weeks ago':
[
2.51 * 7 * a_day,
3.49 * 7 * a_day
],
// 'a month ago':
[
3.51 * 7 * a_day,
1.49 * days_in_a_month * a_day
],
// '2 months ago':
[
1.51 * days_in_a_month * a_day,
2.49 * days_in_a_month * a_day
],
// '3 months ago':
[
2.51 * days_in_a_month * a_day,
3.49 * days_in_a_month * a_day
],
// '4 months ago':
[
3.51 * days_in_a_month * a_day,
4.49 * days_in_a_month * a_day
],
// '5 months ago':
[
4.51 * days_in_a_month * a_day,
5.49 * days_in_a_month * a_day
],
// '6 months ago':
[
5.51 * days_in_a_month * a_day,
6.49 * days_in_a_month * a_day
],
// '7 months ago':
[
6.51 * days_in_a_month * a_day,
7.49 * days_in_a_month * a_day
],
// '8 months ago':
[
7.51 * days_in_a_month * a_day,
8.49 * days_in_a_month * a_day
],
// '9 months ago':
[
8.51 * days_in_a_month * a_day,
8.99 * days_in_a_month * a_day
],
// '9 months ago':
[
9.01 * days_in_a_month * a_day,
9.49 * days_in_a_month * a_day
],
// '10 months ago':
[
9.51 * days_in_a_month * a_day,
10.49 * days_in_a_month * a_day
],
// 'a year ago':
[
10.51 * days_in_a_month * a_day,
1.49 * days_in_a_year * a_day
],
// '2 years ago':
[
1.51 * days_in_a_year * a_day,
2.49 * days_in_a_year * a_day
],
// '3 years ago':
[
2.51 * days_in_a_year * a_day,
3.49 * days_in_a_year * a_day
],
// '100 years ago':
[
99.51 * days_in_a_year * a_day,
100.49 * days_in_a_year * a_day
]
]
'use strict'
// source:
// http://survivejs.com/webpack_react/authoring_libraries/
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var merge = require('webpack-merge')
var minimist = require('minimist')
var pkg = require('./package.json')
var process_arguments = minimist(process.argv.slice(2))
var action = process_arguments.action
if (!action)
{
console.log('Action required.')
console.log('Usage: webpack --target=[dev|gh-pages|build|build-minified]')
return
}
var Root_folder = path.resolve(__dirname)
var Demo_folder = 'demo'
var babel = 'babel?optional[]=runtime&stage=0'
var config =
{
paths:
{
dist: path.join(Root_folder, 'build'),
src: path.join(Root_folder, 'source'),
demo: path.join(Root_folder, Demo_folder),
demoIndex: path.join(Root_folder, Demo_folder, '/index')
},
filename: 'react-isomorphic-render',
library: 'react-isomorphic-render'
}
var merge_demo = merge.bind(null,
{
resolve:
{
extensions: ['', '.js', '.jsx', '.md', '.css', '.png', '.jpg']
},
module:
{
loaders:
[
{
test: /\.css$/,
loaders: ['style', 'css']
},
{
test: /\.md$/,
loaders: ['html', 'highlight', 'markdown']
},
{
test: /\.png$/,
loader: 'url?limit=100000&mimetype=image/png',
include: config.paths.demo
},
{
test: /\.jpg$/,
loader: 'file',
include: config.paths.demo
},
{
test: /\.json$/,
loader: 'json'
}
]
}
})
var merge_build = merge.bind(null,
{
devtool: 'source-map',
output:
{
path: config.paths.dist,
libraryTarget: 'umd',
library: config.library
},
entry: config.paths.src,
externals:
{
//// if you are not testing, just react will do
//react: 'react',
// 'react/addons': 'react/addons'
},
module:
{
loaders:
[
{
test: /\.jsx?$/,
loaders: [babel],
include: config.paths.src
}
]
}
})
switch (action)
{
// Starts WebPack development server
case 'dev':
var IP = '0.0.0.0'
var PORT = 3000
module.exports = merge_demo
({
ip: IP,
port: PORT,
devtool: 'eval',
entry:
[
'webpack-dev-server/client?http://' + IP + ':' + PORT,
'webpack/hot/only-dev-server',
config.paths.demoIndex
],
output:
{
path: __dirname,
filename: 'bundle.js',
publicPath: '/'
},
plugins:
[
new webpack.DefinePlugin
({
'process.env':
{
'NODE_ENV': JSON.stringify('development'),
}
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin()
],
module:
{
preLoaders:
[
{
test: /\.jsx?$/,
loaders: ['eslint', 'jscs'],
include: [config.paths.demo, config.paths.src]
}
],
loaders:
[
{
test: /\.jsx?$/,
loaders: ['react-hot', babel],
include: [config.paths.demo, config.paths.src]
}
]
}
})
break
// Generates a github pages website
case 'gh-pages':
module.exports = merge_demo
({
entry:
{
app: config.paths.demoIndex,
// tweak this to include your externs unless you load them some other way
vendors: ['react/addons']
},
output:
{
path: './gh-pages',
filename: 'bundle.[chunkhash].js'
},
plugins:
[
new webpack.DefinePlugin
({
'process.env':
{
// This has effect on the react lib size
'NODE_ENV': JSON.stringify('production'),
}
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin
({
compress:
{
warnings: false
}
}),
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.[chunkhash].js'),
new HtmlWebpackPlugin
({
title: pkg.name + ' - ' + pkg.description
})
],
module:
{
loaders:
[
{
test: /\.jsx?$/,
loaders: [babel],
include: [config.paths.demo, config.paths.src]
}
]
}
})
break
// Builds the project into a single file
case 'build':
module.exports = merge_build
({
output:
{
filename: config.filename + '.js'
}
})
break
// Builds the project into a single minified file
case 'build-minified':
module.exports = merge_build
({
output:
{
filename: config.filename + '.minified.js'
},
plugins:
[
new webpack.optimize.UglifyJsPlugin
({
compress:
{
warnings: false
}
})
]
})
break
}

Sorry, the diff of this file is not supported yet