diff --git a/.babelrc b/.babelrc deleted file mode 100644 index f4e4578..0000000 --- a/.babelrc +++ /dev/null @@ -1,24 +0,0 @@ -{ - "env": { - "rollup": { - "presets": [ - [ - "@babel/env", - { - "modules": false - } - ] - ], - "plugins": [ - "version" - ] - }, - "babel": { - "presets": ["@babel/env"], - "plugins": [ - "add-module-exports", - "version" - ] - } - } -} diff --git a/.commitlintrc.js b/.commitlintrc.js new file mode 100644 index 0000000..a43666e --- /dev/null +++ b/.commitlintrc.js @@ -0,0 +1,9 @@ +module.exports = { + rules: { + 'type-enum': [ + 2, + 'always', + ['build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test', 'wip'], + ], + }, +}; diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..1cb91e6 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,18 @@ +{ + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.ci.json" + }, + "plugins": ["@typescript-eslint"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "prettier", + "prettier/@typescript-eslint" + ], + "rules": { + "@typescript-eslint/ban-ts-ignore": 1, + "@typescript-eslint/camelcase": 0 + } +} diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..59e5f63 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "bracketSpacing": true, + "printWidth": 120, + "arrowParens": "always" +} diff --git a/.travis.yml b/.travis.yml index a5825f6..f02c4eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,5 +13,7 @@ install: - export DISPLAY=':99.0' - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & - npm install +script: + - npm run ci after_success: - npm run coveralls diff --git a/README.md b/README.md index 51ea125..39fce58 100644 --- a/README.md +++ b/README.md @@ -50,12 +50,11 @@ npm install timeago.js - Import -```js -// ES6 +```ts import { format, render, cancel, register } from 'timeago.js'; -// commonjs -const { format, render, cancel, register } = require('timeago.js'); +// or +import * as timeago from 'timeago.js'; ``` or import with `script` in html file and access global variable `timeago`. @@ -66,7 +65,7 @@ or import with `script` in html file and access global variable `timeago`. - Usage -```js +```ts // format the time with locale format('2016-06-12', 'en_US'); ``` @@ -89,7 +88,7 @@ There only 4 API: Just format date into a string. -```js +```ts import { format, render, cancel, register } from 'timeago.js'; // format timestamp @@ -117,13 +116,15 @@ You can `render` a dom node with automatic rendering. HTML code: ```html -
+
``` Javascript code: -```js -var nodes = document.querySelectorAll('.needs_to_be_rendered'); +```ts +import * as timeago from 'timeago.js'; + +const nodes = document.querySelectorAll('.needs-tobe-rendered'); // use render method to render nodes in real time timeago.render(nodes, 'zh_CN'); @@ -135,7 +136,7 @@ timeago.cancel(); timeago.cancel(nodes[0]) ``` -The input for `render` method should be DOM object / array, pure javascript DOM node or jQuery DOM object supported. +The input for `render` method should be DOM object / array, pure javascript DOM node ~~or jQuery DOM object supported~~. The `cancel` method clears all the render timers and release all resources of the instance. Optionally it accepts a single node to cancel timer just for it. @@ -146,12 +147,12 @@ The `cancel` method clears all the render timers and release all resources of th Default locale is **`en_US`**, and the library supports `en_US` and `zh_CN`. You can register your own language with `register`. -```js +```ts // the local dict example is below. -const localeFunc = (number, index, total_sec) => { +const localeFunc = (number: number, index: number, totalSec: number): [string, string] => { // number: the timeago / timein number; // index: the index of array below; - // total_sec: total seconds between date to be formatted and today's date; + // totalSec: total seconds between date to be formatted and today's date; return [ ['just now', 'right now'], ['%s seconds ago', 'in %s seconds'], @@ -187,7 +188,7 @@ Check out more [locales](src/lang). 2. **locale translations**: The library needs more locale translations. You can: - Open an issue to write the locale translations, or submit a pull request. How to ? see [locales translation](src/lang/). - - Please **test** the locale by exec `npm test`. How to write testcase, see [locales test cases](__tests__/lang/). + - Please **test** the locale by exec `npm test`. How to write test cases, see [locales test cases](__tests__/lang/). diff --git a/README_zh.md b/README_zh.md index 3505a9f..c5b3e2f 100644 --- a/README_zh.md +++ b/README_zh.md @@ -48,12 +48,11 @@ npm install timeago.js - 引入 -```js -// ES6 +```ts import { format, render, cancel, register } from 'timeago.js'; -// commonjs -const { format, render, cancel, register } = require('timeago.js'); +// or +import * as timeago from 'timeago.js'; ``` 或者使用 `script` 在 html 文件中引入,然后就可以使用全局的变量 `timeago`。 @@ -64,7 +63,7 @@ const { format, render, cancel, register } = require('timeago.js'); - 使用 -```js +```ts // 格式化日期 format('2016-06-12', 'en_US'); ``` @@ -115,13 +114,13 @@ format(Date.now() - 11 * 1000 * 60 * 60); // returns '11 hours ago' HTML code: ```html -
+
``` Javascript code: ```js -var nodes = document.querySelectorAll('.needs_to_be_rendered'); +var nodes = document.querySelectorAll('.needs-tobe-rendered'); // use render method to render nodes in real time timeago.render(nodes, 'zh_CN'); @@ -133,9 +132,9 @@ timeago.cancel(); timeago.cancel(nodes[0]) ``` -`render` 函数的输入必须是一个 dom 元素或者数组,JavaScript dom 和 JQuery 的 dom 均支持。 +`render` 函数的输入必须是一个 dom 元素或者数组,JavaScript dom ~~和 JQuery 的 dom 均~~支持。 -`cancel` 清楚实时渲染,如果传入 dom,则清除这个 dom 的实时渲染,否则清除所有。 +`cancel` 清除实时渲染,如果传入 dom,则清除这个 dom 的实时渲染,否则清除所有。 > 被渲染的 dom 元素必须包含一个 `datetime` 属性,用于被格式化的日期。 @@ -146,10 +145,10 @@ timeago.cancel(nodes[0]) ```js // the local dict example is below. -const localeFunc = (number, index, total_sec) => { +const localeFunc = (number, index, totalSec) => { // number: the timeago / timein number; // index: the index of array below; - // total_sec: total seconds between date to be formatted and today's date; + // totalSec: total seconds between date to be formatted and today's date; return [ ['just now', 'right now'], ['%s seconds ago', 'in %s seconds'], diff --git a/__tests__/index.spec.js b/__tests__/index.spec.js deleted file mode 100644 index aeb0693..0000000 --- a/__tests__/index.spec.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Created by hustcc on 18/5/20. - * Contract: i@hust.cc - */ - -import pkg from '../package.json'; -import { format, render, cancel, register, version } from '../src/'; - -describe('index', () => { - test('all', () => { - expect(format).toBeFunction(); - expect(render).toBeFunction(); - expect(cancel).toBeFunction(); - expect(register).toBeFunction(); - - expect(version).toBe(pkg.version); - }); - - test('format', () => { - expect(format(new Date() - 7000)).toBe('just now'); - - expect(format(new Date() - 1000 * 1000, 'zh_CN')).toBe('16 分钟前'); - }); - - test('render', () => { - // render array - render([{}]); - - // render node - render({}); - expect(format(new Date() - 1000 * 1000, 'zh_CN')).toBe('16 分钟前'); - }); - - test('cancel', () => { - cancel(); - - const node = { - getAttribute: () => 1, - }; - - cancel(node); - }); -}); diff --git a/__tests__/index.spec.ts b/__tests__/index.spec.ts new file mode 100644 index 0000000..013d2c8 --- /dev/null +++ b/__tests__/index.spec.ts @@ -0,0 +1,32 @@ +/** + * Created by hustcc on 18/5/20. + * Contract: i@hust.cc + */ + +import { format, render, cancel, register } from '../src/'; + +describe('index', () => { + test('all', () => { + expect(format).toBeInstanceOf(Function); + expect(render).toBeInstanceOf(Function); + expect(cancel).toBeInstanceOf(Function); + expect(register).toBeInstanceOf(Function); + }); + + test('format', () => { + expect(format(+new Date() - 5000)).toBe('just now'); + + expect(format(+new Date() - 1000 * 1000, 'zh_CN')).toBe('16 分钟前'); + }); + + test('cancel', () => { + cancel(); + + const node = { + getAttribute: () => 1, + }; + + // @ts-ignore + cancel(node); + }); +}); diff --git a/__tests__/lang/cs.spec.js b/__tests__/lang/cs.spec.ts similarity index 98% rename from __tests__/lang/cs.spec.js rename to __tests__/lang/cs.spec.ts index d36a7a7..c6ee2a5 100644 --- a/__tests__/lang/cs.spec.js +++ b/__tests__/lang/cs.spec.ts @@ -1,4 +1,4 @@ -import { advanceBy, advanceTo, clear } from 'jest-date-mock'; +import { advanceTo, clear } from 'jest-date-mock'; import { register, format } from '../../src'; import cs from '../../src/lang/cs'; @@ -28,7 +28,6 @@ describe('cs', () => { test('minute', () => { advanceTo(1000 * 60); expect(format(date, 'cs')).toEqual('před minutou'); - }); test('minutes', () => { @@ -49,7 +48,6 @@ describe('cs', () => { test('yesterday', () => { advanceTo(1000 * 60 * 60 * 24); expect(format(date, 'cs')).toEqual('včera'); - }); test('days', () => { @@ -60,7 +58,6 @@ describe('cs', () => { test('last week', () => { advanceTo(1000 * 60 * 60 * 24 * 7); expect(format(date, 'cs')).toEqual('minulý týden'); - }); test('weeks', () => { diff --git a/__tests__/lang/fa.spec.js b/__tests__/lang/fa.spec.ts similarity index 98% rename from __tests__/lang/fa.spec.js rename to __tests__/lang/fa.spec.ts index 34c226a..6407684 100644 --- a/__tests__/lang/fa.spec.js +++ b/__tests__/lang/fa.spec.ts @@ -1,4 +1,4 @@ -import { advanceBy, advanceTo, clear } from 'jest-date-mock'; +import { advanceTo, clear } from 'jest-date-mock'; import { register, format } from '../../src'; import fa from '../../src/lang/fa'; diff --git a/__tests__/lang/he.spec.js b/__tests__/lang/he.spec.ts similarity index 98% rename from __tests__/lang/he.spec.js rename to __tests__/lang/he.spec.ts index ea49823..8ccec6c 100644 --- a/__tests__/lang/he.spec.js +++ b/__tests__/lang/he.spec.ts @@ -1,4 +1,4 @@ -import { advanceBy, advanceTo, clear } from 'jest-date-mock'; +import { advanceTo, clear } from 'jest-date-mock'; import { register, format } from '../../src'; import he from '../../src/lang/he'; diff --git a/__tests__/lang/hi_IN.spec.js b/__tests__/lang/hi_IN.spec.ts similarity index 95% rename from __tests__/lang/hi_IN.spec.js rename to __tests__/lang/hi_IN.spec.ts index 72304e9..b91a930 100644 --- a/__tests__/lang/hi_IN.spec.js +++ b/__tests__/lang/hi_IN.spec.ts @@ -2,13 +2,12 @@ * Created by porcus on 2018/10/09. * Contact: avoicefromthedust@gmail.com */ -import { advanceBy, advanceTo, clear } from 'jest-date-mock'; +import { advanceTo, clear } from 'jest-date-mock'; import { format, register } from '../../src'; import hi_IN from '../../src/lang/hi_IN'; register('hi_IN', hi_IN); - let date = new Date(); beforeEach(() => { diff --git a/__tests__/lang/index.spec.js b/__tests__/lang/index.spec.ts similarity index 100% rename from __tests__/lang/index.spec.js rename to __tests__/lang/index.spec.ts diff --git a/__tests__/lang/it.spec.js b/__tests__/lang/it.spec.ts similarity index 94% rename from __tests__/lang/it.spec.js rename to __tests__/lang/it.spec.ts index 93f7d9e..3caca73 100644 --- a/__tests__/lang/it.spec.js +++ b/__tests__/lang/it.spec.ts @@ -1,4 +1,4 @@ -import { advanceBy, advanceTo, clear } from 'jest-date-mock'; +import { advanceTo, clear } from 'jest-date-mock'; import { register, format } from '../../src'; import it from '../../src/lang/it'; @@ -28,7 +28,7 @@ describe('it', () => { expect(format(date, 'it')).toEqual('30 minuti fa'); advanceTo(1000 * 60 * 60); - expect(format(date, 'it')).toEqual('un\'ora fa'); + expect(format(date, 'it')).toEqual("un'ora fa"); advanceTo(1000 * 60 * 60 * 8); expect(format(date, 'it')).toEqual('8 ore fa'); @@ -71,7 +71,7 @@ describe('it', () => { expect(format(date, 'it')).toEqual('fra 30 minuti'); advanceTo(-1000 * 60 * 60); - expect(format(date, 'it')).toEqual('fra un\'ora'); + expect(format(date, 'it')).toEqual("fra un'ora"); advanceTo(-1000 * 60 * 60 * 8); expect(format(date, 'it')).toEqual('fra 8 ore'); diff --git a/__tests__/lang/ka.spec.js b/__tests__/lang/ka.spec.ts similarity index 98% rename from __tests__/lang/ka.spec.js rename to __tests__/lang/ka.spec.ts index 32fc6f5..91b2ea3 100644 --- a/__tests__/lang/ka.spec.js +++ b/__tests__/lang/ka.spec.ts @@ -2,13 +2,12 @@ * Created by hustcc on 18/5/24. * Contact: i@hust.cc */ -import { advanceBy, advanceTo, clear } from 'jest-date-mock'; +import { advanceTo, clear } from 'jest-date-mock'; import { format, register } from '../../src'; import ka from '../../src/lang/ka'; register('ka', ka); - let date = new Date(); beforeEach(() => { diff --git a/__tests__/lang/nl.spec.js b/__tests__/lang/nl.spec.ts similarity index 97% rename from __tests__/lang/nl.spec.js rename to __tests__/lang/nl.spec.ts index 26df703..dba492b 100644 --- a/__tests__/lang/nl.spec.js +++ b/__tests__/lang/nl.spec.ts @@ -2,13 +2,12 @@ * Created by hustcc on 18/5/24. * Contact: i@hust.cc */ -import { advanceBy, advanceTo, clear } from 'jest-date-mock'; +import { advanceTo, clear } from 'jest-date-mock'; import { format, register } from '../../src'; import nl from '../../src/lang/nl'; register('nl', nl); - let date = new Date(); beforeEach(() => { diff --git a/__tests__/lang/oc.spec.js b/__tests__/lang/oc.spec.ts similarity index 70% rename from __tests__/lang/oc.spec.js rename to __tests__/lang/oc.spec.ts index dd4790d..5c19270 100644 --- a/__tests__/lang/oc.spec.js +++ b/__tests__/lang/oc.spec.ts @@ -1,4 +1,4 @@ -import { advanceBy, advanceTo, clear } from 'jest-date-mock'; +import { advanceTo, clear } from 'jest-date-mock'; import { register, format } from '../../src'; import oc from '../../src/lang/oc'; @@ -59,45 +59,45 @@ describe('oc', () => { }); test('time in', () => { advanceTo(-9 * 1000); - expect(format(date, 'oc')).toEqual('d\'aquí un moment'); + expect(format(date, 'oc')).toEqual("d'aquí un moment"); advanceTo(-30 * 1000); - expect(format(date, 'oc')).toEqual('d\'aquí 30 segondas'); + expect(format(date, 'oc')).toEqual("d'aquí 30 segondas"); advanceTo(-1000 * 60); - expect(format(date, 'oc')).toEqual('d\'aquí 1 minuta'); + expect(format(date, 'oc')).toEqual("d'aquí 1 minuta"); advanceTo(-1000 * 60 * 30); - expect(format(date, 'oc')).toEqual('d\'aquí 30 minutas'); + expect(format(date, 'oc')).toEqual("d'aquí 30 minutas"); advanceTo(-1000 * 60 * 60); - expect(format(date, 'oc')).toEqual('d\'aquí 1 ora'); + expect(format(date, 'oc')).toEqual("d'aquí 1 ora"); advanceTo(-1000 * 60 * 60 * 8); - expect(format(date, 'oc')).toEqual('d\'aquí 8 oras'); + expect(format(date, 'oc')).toEqual("d'aquí 8 oras"); advanceTo(-1000 * 60 * 60 * 24); - expect(format(date, 'oc')).toEqual('d\'aquí 1 jorn'); + expect(format(date, 'oc')).toEqual("d'aquí 1 jorn"); advanceTo(-1000 * 60 * 60 * 24 * 3); - expect(format(date, 'oc')).toEqual('d\'aquí 3 jorns'); + expect(format(date, 'oc')).toEqual("d'aquí 3 jorns"); advanceTo(-1000 * 60 * 60 * 24 * 7); - expect(format(date, 'oc')).toEqual('d\'aquí 1 setmana'); + expect(format(date, 'oc')).toEqual("d'aquí 1 setmana"); advanceTo(-1000 * 60 * 60 * 24 * 7 * 3); - expect(format(date, 'oc')).toEqual('d\'aquí 3 setmanas'); + expect(format(date, 'oc')).toEqual("d'aquí 3 setmanas"); advanceTo(-1000 * 60 * 60 * 24 * 31); - expect(format(date, 'oc')).toEqual('d\'aquí 1 mes'); + expect(format(date, 'oc')).toEqual("d'aquí 1 mes"); advanceTo(-1000 * 60 * 60 * 24 * 31 * 4); - expect(format(date, 'oc')).toEqual('d\'aquí 4 meses'); + expect(format(date, 'oc')).toEqual("d'aquí 4 meses"); advanceTo(-1000 * 60 * 60 * 24 * 366); - expect(format(date, 'oc')).toEqual('d\'aquí 1 an'); + expect(format(date, 'oc')).toEqual("d'aquí 1 an"); advanceTo(-1000 * 60 * 60 * 24 * 366 * 10); - expect(format(date, 'oc')).toEqual('d\'aquí 10 ans'); + expect(format(date, 'oc')).toEqual("d'aquí 10 ans"); }); }); diff --git a/__tests__/lang/zh_TW.spec.js b/__tests__/lang/zh_TW.spec.ts similarity index 98% rename from __tests__/lang/zh_TW.spec.js rename to __tests__/lang/zh_TW.spec.ts index cf8cb90..24a50ed 100644 --- a/__tests__/lang/zh_TW.spec.js +++ b/__tests__/lang/zh_TW.spec.ts @@ -2,7 +2,7 @@ * Created by leoliu1209 on 18/12/11. * Contact: cubemail88@gmail.com */ -import { advanceBy, advanceTo, clear } from 'jest-date-mock'; +import { advanceTo, clear } from 'jest-date-mock'; import { register, format } from '../../src'; import zh_TW from '../../src/lang/zh_TW'; diff --git a/__tests__/locales.spec.js b/__tests__/locales.spec.ts similarity index 98% rename from __tests__/locales.spec.js rename to __tests__/locales.spec.ts index 9c4b6ce..6b2aac0 100644 --- a/__tests__/locales.spec.js +++ b/__tests__/locales.spec.ts @@ -63,8 +63,10 @@ describe('locales', () => { test('register', () => { const fr = () => 'test'; + // @ts-ignore register('fr', fr); expect(getLocale('fr')).toBe(fr); + // @ts-ignore expect(getLocale('fr')()).toBe('test'); }); }); diff --git a/__tests__/utils/date.spec.js b/__tests__/utils/date.spec.ts similarity index 65% rename from __tests__/utils/date.spec.js rename to __tests__/utils/date.spec.ts index f48b448..e3a0a5e 100644 --- a/__tests__/utils/date.spec.js +++ b/__tests__/utils/date.spec.ts @@ -3,37 +3,30 @@ * Contract: i@hust.cc */ -import { - toInt, - toDate, - formatDiff, - diffSec, - nextInterval, -} from '../../src/utils/date'; +import { toDate, formatDiff, diffSec, nextInterval } from '../../src/utils/date'; import { getLocale } from '../../src/locales'; describe('date', () => { - test('toInt', () => { - expect(toInt('a')).toBeNaN(); - }); - // TODO fill all test cases test('toDate', () => { - expect(toDate('1992-08-01') instanceof Date).toEqual(true); - expect(toDate(712627200000) instanceof Date).toEqual(true); + expect(typeof toDate('1992-08-01')).toEqual('number'); + expect(typeof toDate(712627200000)).toEqual('number'); - expect(toDate('2017-2-5 3:57:52UTC') instanceof Date).toEqual(true); - expect(toDate('2017-2-5T3:57:52Z') instanceof Date).toEqual(true); + expect(typeof toDate('2017-2-5 3:57:52UTC')).toEqual('number'); + expect(typeof toDate('2017-2-5T3:57:52Z')).toEqual('number'); - expect(toDate() instanceof Date).toEqual(true); + expect(typeof toDate()).toEqual('number'); }); test('diffSec', () => { const now = new Date(); + // @ts-ignore expect(diffSec(now)).toBeApproximate(0); + // @ts-ignore expect(diffSec(now, now)).toBeApproximate(0); - expect(diffSec(new Date(now - 10000), now)).toBeApproximate(10); + // @ts-ignore + expect(diffSec(new Date(+now - 10000), now)).toBeApproximate(10); }); test('nextInterval', () => { diff --git a/__tests__/utils/dom.spec.js b/__tests__/utils/dom.spec.js deleted file mode 100644 index 131a4c3..0000000 --- a/__tests__/utils/dom.spec.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Created by hustcc on 18/5/20. - * Contract: i@hust.cc - */ - -import { - getTimerId, - saveTimerId, - getDateAttribute -} from '../../src/utils/dom'; - -describe('dom', () => { - test('getTimerId', () => { - const node = { - getAttribute: name => `${name}-native`, - }; - - const jqNode = { - attr: name => `${name}-jq`, - }; - expect(getTimerId(node)).toEqual('timeago-tid-native'); - - expect(getTimerId(jqNode)).toEqual('timeago-tid-jq'); - - expect(getTimerId({})).toEqual(undefined); - }); - - test('getDateAttribute', () => { - const node1 = { - getAttribute: name => { - if (name === 'datetime') return 'datetime-value'; - }, - }; - - const node2 = { - attr: name => { - if (name === 'datetime') return 'datetime-value'; - }, - }; - - expect(getDateAttribute(node1)).toEqual('datetime-value'); - expect(getDateAttribute(node2)).toEqual('datetime-value'); - }); - - test('saveTimerId', () => { - const node1 = { - setAttribute: jest.fn(), - }; - - const node2 = { - attr: jest.fn(), - }; - - saveTimerId({}, 0); - saveTimerId(node1, 1); - saveTimerId(node2, 2); - - expect(node1.setAttribute).toBeCalledWith('timeago-tid', 1); - expect(node2.attr).toBeCalledWith('timeago-tid', 2); - }); -}); diff --git a/__tests__/utils/dom.spec.ts b/__tests__/utils/dom.spec.ts new file mode 100644 index 0000000..c3c6944 --- /dev/null +++ b/__tests__/utils/dom.spec.ts @@ -0,0 +1,44 @@ +/** + * Created by hustcc on 18/5/20. + * Contract: i@hust.cc + */ + +import { getTimerId, getDateAttribute, setTimerId } from '../../src/utils/dom'; + +describe('dom', () => { + test('getTimerId', () => { + const node = { + getAttribute: (name: string): string => '123', + }; + + // @ts-ignore + expect(getTimerId(node)).toEqual(123); + + expect(() => { + // @ts-ignore + getTimerId({}); + }).toThrow(); + }); + + test('getDateAttribute', () => { + const node1 = { + getAttribute: (name) => { + if (name === 'datetime') return 'datetime-value'; + }, + }; + + // @ts-ignore + expect(getDateAttribute(node1)).toEqual('datetime-value'); + }); + + test('setTimerId', () => { + const node1 = { + setAttribute: jest.fn(), + }; + + // @ts-ignore + setTimerId(node1, 1); + + expect(node1.setAttribute).toBeCalledWith('timeago-tid', 1); + }); +}); diff --git a/gh-pages/demo.html b/gh-pages/demo.html index cf1677b..97cb652 100644 --- a/gh-pages/demo.html +++ b/gh-pages/demo.html @@ -31,11 +31,10 @@

What ?

timeago.js is a tiny(2kb) library used to format date with `*** time ago`. eg: '3 hours ago'. No dependency. and support automatically updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). Download, view the examples, and enjoy.

- - - +
+

Test for native DOM

You opened this page @@ -46,16 +45,6 @@

Test for native DOM

You opened this page .

-

Test for Jquery DOM ?

-

- You opened this page . - - -

-

- You opened this page . -

-

Test for Locales ?

You opened this page . @@ -67,23 +56,15 @@

Test for Locales ?

Copyright © 2016 How to user it, see timeago.js. Updated by Hustcc - - - + diff --git a/gh-pages/index.html b/gh-pages/index.html index fd53664..6678944 100644 --- a/gh-pages/index.html +++ b/gh-pages/index.html @@ -61,18 +61,14 @@

How ?

Or you can use ES6 style:

-import timeago from 'timeago.js';
-// or
-var timeago = require("timeago.js");
+import * as timeago from 'timeago.js';

Now, let's attach it to your timestamps on DOM ready:

-timeago().render(document.querySelectorAll('.need_to_be_rendered'));
-// or use jquery selector
-timeago().render($('.need_to_be_rendered'));
+timeago().render(document.querySelectorAll('.need_to_be_rendered'));

- This will realtime render all selected(javascript DOM selector, or jQuery selector all are supported) elements with a class of need_to_be_rendered. + This will realtime render all selected(javascript DOM selector) elements with a class of need_to_be_rendered.

 <span class="need_to_be_rendered" datetime="2016-07-07T09:24:17Z">July 07, 2016</span>
@@ -86,14 +82,13 @@

How ?

Locales register ?

- Yes, timeago.js has locale/i18n/language support. Here are some configuration examples. Please submit a GitHub pull request for corrections or additional languages. + Yes, timeago.js has locale/i18n/language support. Here are some configuration examples. Please submit a GitHub pull request for corrections or additional languages.

-
-var locale = function(number, index, total_sec) {
-  // number: the timeago / timein number;
+var locale = function(number, index, totalSec) {
+  // number: the time ago / time in number;
   // index: the index of array below;
-  // total_sec: total seconds between date to be formatted and today's date;
+  // totalSec: total seconds between date to be formatted and today's date;
   return [
     ['just now', 'right now'],
     ['%s seconds ago', 'in %s seconds'],
@@ -112,9 +107,8 @@ 

Locales register ?

][index]; }; timeago.register('pt_BR', locale); -var timeagoInstance = timeago(); // then you can use it -timeagoInstance.format(1473245023718, 'pt_BR');
+timeago.format(1473245023718, 'pt_BR');

Where ?

Package is managed with npm. so npm install timeago.js will be the latest version.

diff --git a/gh-pages/index.js b/gh-pages/index.js index c23b227..7c82c0e 100644 --- a/gh-pages/index.js +++ b/gh-pages/index.js @@ -19,8 +19,16 @@ function init_index_page() { } function init_test_page() { - $('.native time').attr('datetime', iso8601(new Date())); - $('.jquery time').attr('datetime', iso8601(new Date())); - $('.locales time').attr('datetime', iso8601(new Date())); + document.querySelectorAll('.native time').forEach(function(node) { + node.setAttribute('datetime', iso8601(new Date())); + }); + + document.querySelectorAll('.native time').forEach(function(node) { + node.setAttribute('datetime', iso8601(new Date())); + }); + + document.querySelectorAll('.locales time').forEach(function(node) { + node.setAttribute('datetime', iso8601(new Date())); + }); } diff --git a/gh-pages/timeago.full.min.js b/gh-pages/timeago.full.min.js new file mode 100644 index 0000000..f988d82 --- /dev/null +++ b/gh-pages/timeago.full.min.js @@ -0,0 +1 @@ +!function(s,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((s=s||self).timeago={})}(this,function(s){"use strict";var r=[60,60,24,7,365/7/12,12];function e(s){return s instanceof Date?+s:!isNaN(s)||/^\d+$/.test(s)?+new Date(parseInt(s)):(s=(s||"").trim().replace(/\.\d+/,"").replace(/-/,"/").replace(/-/,"/").replace(/(\d)T(\d)/,"$1 $2").replace(/Z/," UTC").replace(/([+-]\d\d):?(\d\d)/," $1$2"),+new Date(s))}function i(s,n){for(var e=s<0?1:0,a=s=Math.abs(s),t=0;s>=r[t]&&t=r[e]&&e=u[i]&&i=u[n]&&n { - // diff seconds - const sec = diffSec(date, nowDate); - // format it with locale - return formatDiff(sec, getLocale(locale)); -}; diff --git a/src/format.ts b/src/format.ts new file mode 100644 index 0000000..4ee2c8f --- /dev/null +++ b/src/format.ts @@ -0,0 +1,10 @@ +import { formatDiff, diffSec } from './utils/date'; +import { getLocale } from './locales'; +import { TDate } from './interface'; + +export const format = (date: TDate, locale?: string, relativeDate?: TDate): string => { + // diff seconds + const sec = diffSec(date, relativeDate); + // format it with locale + return formatDiff(sec, getLocale(locale)); +}; diff --git a/src/full.ts b/src/full.ts new file mode 100644 index 0000000..b248712 --- /dev/null +++ b/src/full.ts @@ -0,0 +1,13 @@ +/** + * Created by hustcc on 18/5/20. + * Contract: i@hust.cc + */ + +import { format, render, cancel, register } from '.'; +import * as Languages from './lang'; + +Object.keys(Languages).forEach((locale: string) => { + register(locale, Languages[locale]); +}); + +export { format, render, cancel, register }; diff --git a/src/index.js b/src/index.ts similarity index 83% rename from src/index.js rename to src/index.ts index 4a615a1..eb43591 100644 --- a/src/index.js +++ b/src/index.ts @@ -6,5 +6,3 @@ export { format } from './format'; export { render, cancel } from './realtime'; export { register } from './locales'; - -export const version = __VERSION__; diff --git a/src/interface.ts b/src/interface.ts new file mode 100644 index 0000000..45ab453 --- /dev/null +++ b/src/interface.ts @@ -0,0 +1,7 @@ +export type LocaleFunc = (diff: number, idx: number, totalSec?: number) => [string, string]; + +export type LocaleMap = Record; + +export type TDate = Date | string | number; + +export type TimerPool = Record; diff --git a/src/lang/ar.js b/src/lang/ar.js deleted file mode 100644 index 09eb9f9..0000000 --- a/src/lang/ar.js +++ /dev/null @@ -1,27 +0,0 @@ -export default function(number, index) { - if (index === 0) { - return [ 'منذ لحظات', 'بعد لحظات' ]; - } - - var timeStr = formatTime(Math.floor(index/2), number); - return ['منذ' + ' ' + timeStr, 'بعد' + ' ' + timeStr]; -} - -var timeTypes = [ - [ 'ثانية', 'ثانيتين', '%s ثوان', '%s ثانية' ], // Seconds - [ 'دقيقة', 'دقيقتين', '%s دقائق', '%s دقيقة' ], // Minutes - [ 'ساعة', 'ساعتين', '%s ساعات', '%s ساعة' ], // Hours - [ 'يوم', 'يومين', '%s أيام', '%s يوماً' ], // Days - [ 'أسبوع', 'أسبوعين', '%s أسابيع', '%s أسبوعاً' ], // Weeks - [ 'شهر', 'شهرين', '%s أشهر', '%s شهراً' ], // Months - [ 'عام', 'عامين', '%s أعوام', '%s عاماً' ] // Years -]; - -function formatTime(type, n) { - if (n < 3) - return timeTypes[type][n-1]; - else if (n >= 3 && n <= 10) - return timeTypes[type][2]; - else - return timeTypes[type][3]; -} diff --git a/src/lang/ar.ts b/src/lang/ar.ts new file mode 100644 index 0000000..5ceb605 --- /dev/null +++ b/src/lang/ar.ts @@ -0,0 +1,24 @@ +const timeTypes = [ + ['ثانية', 'ثانيتين', '%s ثوان', '%s ثانية'], // Seconds + ['دقيقة', 'دقيقتين', '%s دقائق', '%s دقيقة'], // Minutes + ['ساعة', 'ساعتين', '%s ساعات', '%s ساعة'], // Hours + ['يوم', 'يومين', '%s أيام', '%s يوماً'], // Days + ['أسبوع', 'أسبوعين', '%s أسابيع', '%s أسبوعاً'], // Weeks + ['شهر', 'شهرين', '%s أشهر', '%s شهراً'], // Months + ['عام', 'عامين', '%s أعوام', '%s عاماً'], // Years +]; + +function formatTime(type: number, n: number): string { + if (n < 3) return timeTypes[type][n - 1]; + if (n >= 3 && n <= 10) return timeTypes[type][2]; + return timeTypes[type][3]; +} + +export default function(number: number, index: number): [string, string] { + if (index === 0) { + return ['منذ لحظات', 'بعد لحظات']; + } + + const timeStr = formatTime(Math.floor(index / 2), number); + return ['منذ' + ' ' + timeStr, 'بعد' + ' ' + timeStr]; +} diff --git a/src/lang/be.js b/src/lang/be.js deleted file mode 100644 index 7bb459b..0000000 --- a/src/lang/be.js +++ /dev/null @@ -1,51 +0,0 @@ -var seconds = formatNum.bind(null, 'секунду', '%s секунду', '%s секунды', '%s секунд'), - minutes = formatNum.bind(null, 'хвіліну', '%s хвіліну', '%s хвіліны', '%s хвілін'), - hours = formatNum.bind(null, 'гадзіну', '%s гадзіну', '%s гадзіны', '%s гадзін'), - days = formatNum.bind(null, 'дзень', '%s дзень', '%s дні', '%s дзён'), - weeks = formatNum.bind(null, 'тыдзень', '%s тыдзень', '%s тыдні', '%s тыдняў'), - months = formatNum.bind(null, 'месяц', '%s месяц', '%s месяцы', '%s месяцаў'), - years = formatNum.bind(null, 'год', '%s год', '%s гады', '%s гадоў'); - -export default function(number, index) { - switch(index) { - case 0: return ['толькі што', 'праз некалькі секунд']; - case 1: return [seconds(number) + ' таму', 'праз ' + seconds(number)]; - case 2: - case 3: return [minutes(number) + ' таму', 'праз ' + minutes(number)]; - case 4: - case 5: return [hours(number) + ' таму', 'праз ' + hours(number)]; - case 6: - case 7: return [days(number) + ' таму', 'праз ' + days(number)]; - case 8: - case 9: return [weeks(number) + ' таму', 'праз ' + weeks(number)]; - case 10: - case 11: return [months(number) + ' таму', 'праз ' + months(number)]; - case 12: - case 13: return [years(number) + ' таму', 'праз ' + years(number)]; - default: return ['', ''] - } -}; - -/** - * - * @param f1 - 1 - * @param f - 21, 31, ... - * @param s - 2-4, 22-24, 32-34 ... - * @param t - 5-20, 25-30, ... - * @param n - * @returns {string} - */ -function formatNum(f1, f, s, t, n) { - var n10 = n % 10, - str = t; - - if (n === 1) { - str = f1; - } else if (n10 === 1 && n > 20) { - str = f; - } else if (n10 > 1 && n10 < 5 && (n > 20 || n < 10)) { - str = s; - } - - return str; -} diff --git a/src/lang/be.ts b/src/lang/be.ts new file mode 100644 index 0000000..ee72166 --- /dev/null +++ b/src/lang/be.ts @@ -0,0 +1,60 @@ +/** + * + * @param f1 - 1 + * @param f - 21, 31, ... + * @param s - 2-4, 22-24, 32-34 ... + * @param t - 5-20, 25-30, ... + * @param n + * @returns + */ +function formatNum(f1: string, f: string, s: string, t: string, n: number): string { + const n10 = n % 10; + let str = t; + + if (n === 1) { + str = f1; + } else if (n10 === 1 && n > 20) { + str = f; + } else if (n10 > 1 && n10 < 5 && (n > 20 || n < 10)) { + str = s; + } + + return str; +} + +const seconds = formatNum.bind(null, 'секунду', '%s секунду', '%s секунды', '%s секунд'), + minutes = formatNum.bind(null, 'хвіліну', '%s хвіліну', '%s хвіліны', '%s хвілін'), + hours = formatNum.bind(null, 'гадзіну', '%s гадзіну', '%s гадзіны', '%s гадзін'), + days = formatNum.bind(null, 'дзень', '%s дзень', '%s дні', '%s дзён'), + weeks = formatNum.bind(null, 'тыдзень', '%s тыдзень', '%s тыдні', '%s тыдняў'), + months = formatNum.bind(null, 'месяц', '%s месяц', '%s месяцы', '%s месяцаў'), + years = formatNum.bind(null, 'год', '%s год', '%s гады', '%s гадоў'); + +export default function(number: number, index: number): [string, string] { + switch (index) { + case 0: + return ['толькі што', 'праз некалькі секунд']; + case 1: + return [seconds(number) + ' таму', 'праз ' + seconds(number)]; + case 2: + case 3: + return [minutes(number) + ' таму', 'праз ' + minutes(number)]; + case 4: + case 5: + return [hours(number) + ' таму', 'праз ' + hours(number)]; + case 6: + case 7: + return [days(number) + ' таму', 'праз ' + days(number)]; + case 8: + case 9: + return [weeks(number) + ' таму', 'праз ' + weeks(number)]; + case 10: + case 11: + return [months(number) + ' таму', 'праз ' + months(number)]; + case 12: + case 13: + return [years(number) + ' таму', 'праз ' + years(number)]; + default: + return ['', '']; + } +} diff --git a/src/lang/bg.js b/src/lang/bg.ts similarity index 82% rename from src/lang/bg.js rename to src/lang/bg.ts index 8e6b5cf..9b6b1e0 100644 --- a/src/lang/bg.js +++ b/src/lang/bg.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['току що', 'съвсем скоро'], ['преди %s секунди', 'след %s секунди'], @@ -13,6 +13,6 @@ export default function(number, index) { ['преди 1 месец', 'след 1 месец'], ['преди %s месеца', 'след %s месеца'], ['преди 1 година', 'след 1 година'], - ['преди %s години', 'след %s години'] - ][index]; + ['преди %s години', 'след %s години'], + ][index] as [string, string]; } diff --git a/src/lang/bn_IN.js b/src/lang/bn_IN.js deleted file mode 100644 index 59e2816..0000000 --- a/src/lang/bn_IN.js +++ /dev/null @@ -1,19 +0,0 @@ -// Bangla (India) -export default function(number, index) { - return [ - [ 'এইমাত্র' , 'একটা সময়'] , - [ '%s সেকেন্ড আগে', '%s এর সেকেন্ডের মধ্যে'] , - [ '1 মিনিট আগে', '1 মিনিটে'] , - [ '%s এর মিনিট আগে', '%s এর মিনিটের মধ্যে'] , - [ '1 ঘন্টা আগে', '1 ঘন্টা'] , - [ '%s ঘণ্টা আগে', '%s এর ঘন্টার মধ্যে'] , - [ '1 দিন আগে', '1 দিনের মধ্যে'] , - [ '%s এর দিন আগে', '%s এর দিন'] , - [ '1 সপ্তাহ আগে', '1 সপ্তাহের মধ্যে'] , - [ '%s এর সপ্তাহ আগে', '%s সপ্তাহের মধ্যে'] , - [ '1 মাস আগে', '1 মাসে'] , - [ '%s মাস আগে', '%s মাসে'] , - [ '1 বছর আগে', '1 বছরের মধ্যে'] , - [ '%s বছর আগে', '%s বছরে'] - ][index]; -} diff --git a/src/lang/bn_IN.ts b/src/lang/bn_IN.ts new file mode 100644 index 0000000..bb924b8 --- /dev/null +++ b/src/lang/bn_IN.ts @@ -0,0 +1,19 @@ +// Bangla (India) +export default function(number: number, index: number): [string, string] { + return [ + ['এইমাত্র', 'একটা সময়'], + ['%s সেকেন্ড আগে', '%s এর সেকেন্ডের মধ্যে'], + ['1 মিনিট আগে', '1 মিনিটে'], + ['%s এর মিনিট আগে', '%s এর মিনিটের মধ্যে'], + ['1 ঘন্টা আগে', '1 ঘন্টা'], + ['%s ঘণ্টা আগে', '%s এর ঘন্টার মধ্যে'], + ['1 দিন আগে', '1 দিনের মধ্যে'], + ['%s এর দিন আগে', '%s এর দিন'], + ['1 সপ্তাহ আগে', '1 সপ্তাহের মধ্যে'], + ['%s এর সপ্তাহ আগে', '%s সপ্তাহের মধ্যে'], + ['1 মাস আগে', '1 মাসে'], + ['%s মাস আগে', '%s মাসে'], + ['1 বছর আগে', '1 বছরের মধ্যে'], + ['%s বছর আগে', '%s বছরে'], + ][index] as [string, string]; +} diff --git a/src/lang/ca.js b/src/lang/ca.js deleted file mode 100644 index e15651b..0000000 --- a/src/lang/ca.js +++ /dev/null @@ -1,18 +0,0 @@ -export default function(number, index) { - return [ - ['fa un moment', 'd\'aquí un moment'], - ['fa %s segons', 'd\'aquí %s segons'], - ['fa 1 minut', 'd\'aquí 1 minut'], - ['fa %s minuts', 'd\'aquí %s minuts'], - ['fa 1 hora', 'd\'aquí 1 hora'], - ['fa %s hores', 'd\'aquí %s hores'], - ['fa 1 dia', 'd\'aquí 1 dia'], - ['fa %s dies', 'd\'aquí %s dies'], - ['fa 1 setmana', 'd\'aquí 1 setmana'], - ['fa %s setmanes', 'd\'aquí %s setmanes'], - ['fa 1 mes', 'd\'aquí 1 mes'], - ['fa %s mesos', 'd\'aquí %s mesos'], - ['fa 1 any', 'd\'aquí 1 any'], - ['fa %s anys', 'd\'aquí %s anys'] - ][index]; -} diff --git a/src/lang/ca.ts b/src/lang/ca.ts new file mode 100644 index 0000000..f51c019 --- /dev/null +++ b/src/lang/ca.ts @@ -0,0 +1,18 @@ +export default function(number: number, index: number): [string, string] { + return [ + ['fa un moment', "d'aquí un moment"], + ['fa %s segons', "d'aquí %s segons"], + ['fa 1 minut', "d'aquí 1 minut"], + ['fa %s minuts', "d'aquí %s minuts"], + ['fa 1 hora', "d'aquí 1 hora"], + ['fa %s hores', "d'aquí %s hores"], + ['fa 1 dia', "d'aquí 1 dia"], + ['fa %s dies', "d'aquí %s dies"], + ['fa 1 setmana', "d'aquí 1 setmana"], + ['fa %s setmanes', "d'aquí %s setmanes"], + ['fa 1 mes', "d'aquí 1 mes"], + ['fa %s mesos', "d'aquí %s mesos"], + ['fa 1 any', "d'aquí 1 any"], + ['fa %s anys', "d'aquí %s anys"], + ][index] as [string, string]; +} diff --git a/src/lang/cs.js b/src/lang/cs.js deleted file mode 100644 index 2fe0d5d..0000000 --- a/src/lang/cs.js +++ /dev/null @@ -1,60 +0,0 @@ -module.exports = function (number, index) { - let inflectionIndex = 0; - - let isInflectionNeeded = index == 1 || - index == 3 || - index == 5 || - index == 7 || - index == 9 || - index == 11 || - index == 13; - if (isInflectionNeeded && number >= 5) { - inflectionIndex = 1; - } - - return [ - [ - ['právě teď', 'právě teď'] - ], - [ - ['před %s vteřinami', 'za %s vteřiny'], - ['před %s vteřinami', 'za %s vteřin'] - ], - [['před minutou', 'za minutu']], - [ - ['před %s minutami', 'za %s minuty'], - ['před %s minutami', 'za %s minut'] - ], - [['před hodinou', 'za hodinu']], - [ - ['před %s hodinami', 'za %s hodiny'], - ['před %s hodinami', 'za %s hodin'], - ], - [['včera', 'zítra']], - [ - ['před %s dny', 'za %s dny'], - ['před %s dny', 'za %s dnů'], - ], - [ - ['minulý týden', 'příští týden'] - ], - [ - ['před %s týdny', 'za %s týdny'], - ['před %s týdny', 'za %s týdnů'], - ], - [ - ['minulý měsíc', 'přístí měsíc'] - ], - [ - ['před %s měsíci', 'za %s měsíce'], - ['před %s měsíci', 'za %s měsíců'], - ], - [ - ['před rokem', 'přístí rok'] - ], - [ - ['před %s lety', 'za %s roky'], - ['před %s lety', 'za %s let'] - ] - ][index][inflectionIndex]; -} diff --git a/src/lang/cs.ts b/src/lang/cs.ts new file mode 100644 index 0000000..ef835bf --- /dev/null +++ b/src/lang/cs.ts @@ -0,0 +1,26 @@ +export default function(number: number, index: number): [string, string] { + let inflectionIndex = 0; + + const isInflectionNeeded = + index == 1 || index == 3 || index == 5 || index == 7 || index == 9 || index == 11 || index == 13; + if (isInflectionNeeded && number >= 5) { + inflectionIndex = 1; + } + + return [ + [['právě teď', 'právě teď']], + [['před %s vteřinami', 'za %s vteřiny'], ['před %s vteřinami', 'za %s vteřin']], + [['před minutou', 'za minutu']], + [['před %s minutami', 'za %s minuty'], ['před %s minutami', 'za %s minut']], + [['před hodinou', 'za hodinu']], + [['před %s hodinami', 'za %s hodiny'], ['před %s hodinami', 'za %s hodin']], + [['včera', 'zítra']], + [['před %s dny', 'za %s dny'], ['před %s dny', 'za %s dnů']], + [['minulý týden', 'příští týden']], + [['před %s týdny', 'za %s týdny'], ['před %s týdny', 'za %s týdnů']], + [['minulý měsíc', 'přístí měsíc']], + [['před %s měsíci', 'za %s měsíce'], ['před %s měsíci', 'za %s měsíců']], + [['před rokem', 'přístí rok']], + [['před %s lety', 'za %s roky'], ['před %s lety', 'za %s let']], + ][index][inflectionIndex] as [string, string]; +} diff --git a/src/lang/da.js b/src/lang/da.ts similarity index 79% rename from src/lang/da.js rename to src/lang/da.ts index 648b9bf..310d409 100644 --- a/src/lang/da.js +++ b/src/lang/da.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['for et øjeblik siden', 'om et øjeblik'], ['for %s sekunder siden', 'om %s sekunder'], @@ -13,6 +13,6 @@ export default function(number, index) { ['for 1 måned siden', 'om 1 måned'], ['for %s måneder siden', 'om %s måneder'], ['for 1 år siden', 'om 1 år'], - ['for %s år siden', 'om %s år'] - ][index]; + ['for %s år siden', 'om %s år'], + ][index] as [string, string]; } diff --git a/src/lang/de.js b/src/lang/de.ts similarity index 77% rename from src/lang/de.js rename to src/lang/de.ts index cbce5b9..2652a9d 100644 --- a/src/lang/de.js +++ b/src/lang/de.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['gerade eben', 'vor einer Weile'], ['vor %s Sekunden', 'in %s Sekunden'], @@ -13,6 +13,6 @@ export default function(number, index) { ['vor 1 Monat', 'in 1 Monat'], ['vor %s Monaten', 'in %s Monaten'], ['vor 1 Jahr', 'in 1 Jahr'], - ['vor %s Jahren', 'in %s Jahren'] - ][index]; + ['vor %s Jahren', 'in %s Jahren'], + ][index] as [string, string]; } diff --git a/src/lang/el.js b/src/lang/el.ts similarity index 81% rename from src/lang/el.js rename to src/lang/el.ts index ebfaf39..74d43f6 100644 --- a/src/lang/el.js +++ b/src/lang/el.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['μόλις τώρα', 'σε λίγο'], ['%s δευτερόλεπτα πριν', 'σε %s δευτερόλεπτα'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 μήνα πριν', 'σε 1 μήνα'], ['%s μήνες πριν', 'σε %s μήνες'], ['1 χρόνο πριν', 'σε 1 χρόνο'], - ['%s χρόνια πριν', 'σε %s χρόνια'] - ][index]; + ['%s χρόνια πριν', 'σε %s χρόνια'], + ][index] as [string, string]; } diff --git a/src/lang/en_US.ts b/src/lang/en_US.ts new file mode 100644 index 0000000..1472f40 --- /dev/null +++ b/src/lang/en_US.ts @@ -0,0 +1,8 @@ +const EN_US = ['second', 'minute', 'hour', 'day', 'week', 'month', 'year']; + +export default function(diff: number, idx: number): [string, string] { + if (idx === 0) return ['just now', 'right now']; + let unit = EN_US[~~(idx / 2)]; + if (diff > 1) unit += 's'; + return [`${diff} ${unit} ago`, `in ${diff} ${unit}`]; +} diff --git a/src/lang/en_short.js b/src/lang/en_short.ts similarity index 72% rename from src/lang/en_short.js rename to src/lang/en_short.ts index 84e9e52..263557f 100644 --- a/src/lang/en_short.js +++ b/src/lang/en_short.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['just now', 'right now'], ['%ss ago', 'in %ss'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1mo ago', 'in 1mo'], ['%smo ago', 'in %smo'], ['1yr ago', 'in 1yr'], - ['%syr ago', 'in %syr'] - ][index]; + ['%syr ago', 'in %syr'], + ][index] as [string, string]; } diff --git a/src/lang/es.js b/src/lang/es.ts similarity index 77% rename from src/lang/es.js rename to src/lang/es.ts index c7e05fb..4d9ce6a 100644 --- a/src/lang/es.js +++ b/src/lang/es.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['justo ahora', 'en un rato'], ['hace %s segundos', 'en %s segundos'], @@ -13,6 +13,6 @@ export default function(number, index) { ['hace 1 mes', 'en 1 mes'], ['hace %s meses', 'en %s meses'], ['hace 1 año', 'en 1 año'], - ['hace %s años', 'en %s años'] - ][index]; -}; + ['hace %s años', 'en %s años'], + ][index] as [string, string]; +} diff --git a/src/lang/eu.js b/src/lang/eu.ts similarity index 78% rename from src/lang/eu.js rename to src/lang/eu.ts index c25158a..ebb2582 100644 --- a/src/lang/eu.js +++ b/src/lang/eu.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['orain', 'denbora bat barru'], ['duela %s segundu', '%s segundu barru'], @@ -13,6 +13,6 @@ export default function(number, index) { ['duela hillabete 1', 'hillabete 1 barru'], ['duela %s hillabete', '%s hillabete barru'], ['duela urte 1', 'urte 1 barru'], - ['duela %s urte', '%s urte barru'] - ][index]; + ['duela %s urte', '%s urte barru'], + ][index] as [string, string]; } diff --git a/src/lang/fa.js b/src/lang/fa.ts similarity index 71% rename from src/lang/fa.js rename to src/lang/fa.ts index 8f560d4..47d4e2c 100644 --- a/src/lang/fa.js +++ b/src/lang/fa.ts @@ -1,5 +1,14 @@ -export default function (number, index) { - var formattedString = [ +// As persian language has different number symbols we need to replace regular numbers +// to standard persian numbres. +function toPersianNumber(number): string { + // List of standard persian numbers from 0 to 9 + const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']; + + return number.toString().replace(/\d/g, (x) => persianDigits[x]); +} + +export default function(number: number, index: number): [string, string] { + const formattedString = [ ['لحظاتی پیش', 'همین حالا'], ['%s ثانیه پیش', '%s ثانیه دیگر'], ['۱ دقیقه پیش', '۱ دقیقه دیگر'], @@ -13,20 +22,12 @@ export default function (number, index) { ['۱ ماه پیش', '۱ ماه دیگر'], ['%s ماه پیش', '%s ماه دیگر'], ['۱ سال پیش', '۱ سال دیگر'], - ['%s سال پیش', '%s سال دیگر'] + ['%s سال پیش', '%s سال دیگر'], ][index]; // We convert regular numbers (%s) to standard persian numbers using toPersianNumber function - return [formattedString[0].replace('%s', toPersianNumber(number)), formattedString[1].replace('%s', toPersianNumber(number))]; + return [ + formattedString[0].replace('%s', toPersianNumber(number)), + formattedString[1].replace('%s', toPersianNumber(number)), + ]; } - -// As persian language has different number symbols we need to replace regular numbers -// to standard persian numbres. -function toPersianNumber(number) { - // List of standard persian numbers from 0 to 9 - const persianDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹']; - - return number - .toString() - .replace(/\d/g, x => persianDigits[x]); -} \ No newline at end of file diff --git a/src/lang/fi.js b/src/lang/fi.ts similarity index 80% rename from src/lang/fi.js rename to src/lang/fi.ts index 162be0e..dc881e3 100644 --- a/src/lang/fi.js +++ b/src/lang/fi.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['juuri äsken', 'juuri nyt'], ['%s sekuntia sitten', '%s sekunnin päästä'], @@ -13,6 +13,6 @@ export default function(number, index) { ['kuukausi sitten', 'kuukauden päästä'], ['%s kuukautta sitten', '%s kuukauden päästä'], ['vuosi sitten', 'vuoden päästä'], - ['%s vuotta sitten', '%s vuoden päästä'] - ][index]; + ['%s vuotta sitten', '%s vuoden päästä'], + ][index] as [string, string]; } diff --git a/src/lang/fr.js b/src/lang/fr.ts similarity index 73% rename from src/lang/fr.js rename to src/lang/fr.ts index 72f435d..e2fdbce 100644 --- a/src/lang/fr.js +++ b/src/lang/fr.ts @@ -1,6 +1,6 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ - ['à l\'instant', 'dans un instant'], + ["à l'instant", 'dans un instant'], ['il y a %s secondes', 'dans %s secondes'], ['il y a 1 minute', 'dans 1 minute'], ['il y a %s minutes', 'dans %s minutes'], @@ -13,6 +13,6 @@ export default function(number, index) { ['il y a 1 mois', 'dans 1 mois'], ['il y a %s mois', 'dans %s mois'], ['il y a 1 an', 'dans 1 an'], - ['il y a %s ans', 'dans %s ans'] - ][index]; + ['il y a %s ans', 'dans %s ans'], + ][index] as [string, string]; } diff --git a/src/lang/gl.js b/src/lang/gl.ts similarity index 77% rename from src/lang/gl.js rename to src/lang/gl.ts index 2ef23b3..b434528 100644 --- a/src/lang/gl.js +++ b/src/lang/gl.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['xusto agora', 'daquí a un pouco'], ['hai %s segundos', 'en %s segundos'], @@ -13,6 +13,6 @@ export default function(number, index) { ['hai 1 mes', 'nun mes'], ['hai %s meses', 'en %s meses'], ['hai 1 ano', 'nun ano'], - ['hai %s anos', 'en %s anos'] - ][index]; -}; + ['hai %s anos', 'en %s anos'], + ][index] as [string, string]; +} diff --git a/src/lang/he.js b/src/lang/he.js deleted file mode 100644 index 0ef1af5..0000000 --- a/src/lang/he.js +++ /dev/null @@ -1,18 +0,0 @@ -export default function(number, index) { - return [ - ['זה עתה', 'עכשיו'], - ['לפני %s שניות', 'בעוד %s שניות'], - ['לפני דקה', 'בעוד דקה'], - ['לפני %s דקות', 'בעוד %s דקות'], - ['לפני שעה', 'בעוד שעה'], - number === 2 ? ['לפני שעתיים', 'בעוד שעתיים'] : ['לפני %s שעות', 'בעוד %s שעות'], - ['אתמול', 'מחר'], - number === 2 ? ['לפני יומיים', 'בעוד יומיים'] : ['לפני %s ימים', 'בעוד %s ימים'], - ['לפני שבוע', 'בעוד שבוע'], - number === 2 ? ['לפני שבועיים', 'בעוד שבועיים'] : ['לפני %s שבועות', 'בעוד %s שבועות'], - ['לפני חודש', 'בעוד חודש'], - number === 2 ? ['לפני חודשיים', 'בעוד חודשיים'] : ['לפני %s חודשים', 'בעוד %s חודשים'], - ['לפני שנה', 'בעוד שנה'], - number === 2 ? ['לפני שנתיים', 'בעוד שנתיים'] : ['לפני %s שנים', 'בעוד %s שנים'] - ][index]; -} diff --git a/src/lang/he.ts b/src/lang/he.ts new file mode 100644 index 0000000..4e5aa69 --- /dev/null +++ b/src/lang/he.ts @@ -0,0 +1,18 @@ +export default function(number: number, index: number): [string, string] { + return [ + ['זה עתה', 'עכשיו'], + ['לפני %s שניות', 'בעוד %s שניות'], + ['לפני דקה', 'בעוד דקה'], + ['לפני %s דקות', 'בעוד %s דקות'], + ['לפני שעה', 'בעוד שעה'], + number === 2 ? ['לפני שעתיים', 'בעוד שעתיים'] : ['לפני %s שעות', 'בעוד %s שעות'], + ['אתמול', 'מחר'], + number === 2 ? ['לפני יומיים', 'בעוד יומיים'] : ['לפני %s ימים', 'בעוד %s ימים'], + ['לפני שבוע', 'בעוד שבוע'], + number === 2 ? ['לפני שבועיים', 'בעוד שבועיים'] : ['לפני %s שבועות', 'בעוד %s שבועות'], + ['לפני חודש', 'בעוד חודש'], + number === 2 ? ['לפני חודשיים', 'בעוד חודשיים'] : ['לפני %s חודשים', 'בעוד %s חודשים'], + ['לפני שנה', 'בעוד שנה'], + number === 2 ? ['לפני שנתיים', 'בעוד שנתיים'] : ['לפני %s שנים', 'בעוד %s שנים'], + ][index] as [string, string]; +} diff --git a/src/lang/hi_IN.js b/src/lang/hi_IN.ts similarity index 60% rename from src/lang/hi_IN.js rename to src/lang/hi_IN.ts index 87dbe25..a55a6b7 100644 --- a/src/lang/hi_IN.js +++ b/src/lang/hi_IN.ts @@ -1,19 +1,19 @@ // Hindi (India) -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['अभी', 'कुछ समय'], ['%s सेकंड पहले', '%s सेकंड में'], ['1 मिनट पहले', '1 मिनट में'], - ['%s मिनट पहले', '%s मिनट में'] , - ['1 घंटे पहले', '1 घंटे में'] , - ['%s घंटे पहले', '%s घंटे में'] , - ['1 दिन पहले', '1 दिन में'] , - ['%s दिन पहले', '%s दिनों में'] , - ['1 सप्ताह पहले', '1 सप्ताह में'] , - ['%s हफ्ते पहले', '%s हफ्तों में'] , - ['1 महीने पहले', '1 महीने में'] , - ['%s महीने पहले', '%s महीनों में'] , - ['1 साल पहले', '1 साल में'] , - ['%s साल पहले','%s साल में'] - ][index]; + ['%s मिनट पहले', '%s मिनट में'], + ['1 घंटे पहले', '1 घंटे में'], + ['%s घंटे पहले', '%s घंटे में'], + ['1 दिन पहले', '1 दिन में'], + ['%s दिन पहले', '%s दिनों में'], + ['1 सप्ताह पहले', '1 सप्ताह में'], + ['%s हफ्ते पहले', '%s हफ्तों में'], + ['1 महीने पहले', '1 महीने में'], + ['%s महीने पहले', '%s महीनों में'], + ['1 साल पहले', '1 साल में'], + ['%s साल पहले', '%s साल में'], + ][index] as [string, string]; } diff --git a/src/lang/hu.js b/src/lang/hu.ts similarity index 78% rename from src/lang/hu.js rename to src/lang/hu.ts index 9e936ee..ba55831 100644 --- a/src/lang/hu.js +++ b/src/lang/hu.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['éppen most', 'éppen most'], ['%s másodperce', '%s másodpercen belül'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 hónapja', '1 hónapon belül'], ['%s hónapja', '%s hónapon belül'], ['1 éve', '1 éven belül'], - ['%s éve', '%s éven belül'] - ][index]; + ['%s éve', '%s éven belül'], + ][index] as [string, string]; } diff --git a/src/lang/id_ID.js b/src/lang/id_ID.ts similarity index 79% rename from src/lang/id_ID.js rename to src/lang/id_ID.ts index af8e2cf..25de915 100644 --- a/src/lang/id_ID.js +++ b/src/lang/id_ID.ts @@ -1,5 +1,5 @@ // Indonesian (Indonesia) -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['baru saja', 'sebentar'], ['%s detik yang lalu', 'dalam %s detik'], @@ -14,6 +14,6 @@ export default function(number, index) { ['1 bulan yang lalu', 'dalam 1 bulan'], ['%s bulan yang lalu', 'dalam %s bulan'], ['1 tahun yang lalu', 'dalam 1 tahun'], - ['%s tahun yang lalu', 'dalam %s tahun'] - ][index]; + ['%s tahun yang lalu', 'dalam %s tahun'], + ][index] as [string, string]; } diff --git a/src/lang/index.js b/src/lang/index.ts similarity index 97% rename from src/lang/index.js rename to src/lang/index.ts index af7c82e..c54107c 100644 --- a/src/lang/index.js +++ b/src/lang/index.ts @@ -6,6 +6,7 @@ export { default as ca } from './ca'; export { default as de } from './de'; export { default as el } from './el'; export { default as en_short } from './en_short'; +export { default as en_US } from './en_US'; export { default as es } from './es'; export { default as eu } from './eu'; export { default as fa } from './fa'; diff --git a/src/lang/it.js b/src/lang/it.ts similarity index 72% rename from src/lang/it.js rename to src/lang/it.ts index a206a64..499a9a2 100644 --- a/src/lang/it.js +++ b/src/lang/it.ts @@ -1,10 +1,10 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['poco fa', 'fra poco'], ['%s secondi fa', 'fra %s secondi'], ['un minuto fa', 'fra un minuto'], ['%s minuti fa', 'fra %s minuti'], - ['un\'ora fa', 'fra un\'ora'], + ["un'ora fa", "fra un'ora"], ['%s ore fa', 'fra %s ore'], ['un giorno fa', 'fra un giorno'], ['%s giorni fa', 'fra %s giorni'], @@ -13,6 +13,6 @@ export default function(number, index) { ['un mese fa', 'fra un mese'], ['%s mesi fa', 'fra %s mesi'], ['un anno fa', 'fra un anno'], - ['%s anni fa', 'fra %s anni'] - ][index]; + ['%s anni fa', 'fra %s anni'], + ][index] as [string, string]; } diff --git a/src/lang/ja.js b/src/lang/ja.ts similarity index 76% rename from src/lang/ja.js rename to src/lang/ja.ts index ca6714f..25b17cc 100644 --- a/src/lang/ja.js +++ b/src/lang/ja.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['すこし前', 'すぐに'], ['%s秒前', '%s秒以内'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1ヶ月前', '1ヶ月以内'], ['%sヶ月前', '%sヶ月以内'], ['1年前', '1年以内'], - ['%s年前', '%s年以内'] - ][index]; + ['%s年前', '%s年以内'], + ][index] as [string, string]; } diff --git a/src/lang/ka.js b/src/lang/ka.ts similarity index 88% rename from src/lang/ka.js rename to src/lang/ka.ts index 5a2ef6b..d74844a 100644 --- a/src/lang/ka.js +++ b/src/lang/ka.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['ამ წამს', 'ახლა'], ['%s წამის წინ', '%s წამში'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 თვის წინ', '1 თვეში'], ['%s თვის წინ', '%s თვეში'], ['1 წლის წინ', '1 წელიწადში'], - ['%s წლის წინ', '%s წელიწადში'] - ][index]; + ['%s წლის წინ', '%s წელიწადში'], + ][index] as [string, string]; } diff --git a/src/lang/ko.js b/src/lang/ko.ts similarity index 76% rename from src/lang/ko.js rename to src/lang/ko.ts index 00f3a93..ad9c4cc 100644 --- a/src/lang/ko.js +++ b/src/lang/ko.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['방금', '곧'], ['%s초 전', '%s초 후'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1개월 전', '1개월 후'], ['%s개월 전', '%s개월 후'], ['1년 전', '1년 후'], - ['%s년 전', '%s년 후'] - ][index]; + ['%s년 전', '%s년 후'], + ][index] as [string, string]; } diff --git a/src/lang/ml.js b/src/lang/ml.ts similarity index 92% rename from src/lang/ml.js rename to src/lang/ml.ts index ac02beb..81baede 100644 --- a/src/lang/ml.js +++ b/src/lang/ml.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['ഇപ്പോള്‍', 'കുറച്ചു മുന്‍പ്'], ['%s സെക്കന്റ്‌കള്‍ക്ക് മുന്‍പ്', '%s സെക്കന്റില്‍'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 മാസത്തിനു മുന്‍പ്', '1 മാസത്തിനുള്ളില്‍'], ['%s മാസങ്ങള്‍ക്ക് മുന്‍പ്', '%s മാസങ്ങള്‍ക്കുള്ളില്‍'], ['1 വര്‍ഷത്തിനു മുന്‍പ്', '1 വര്‍ഷത്തിനുള്ളില്‍'], - ['%s വര്‍ഷങ്ങള്‍ക്കു മുന്‍പ്', '%s വര്‍ഷങ്ങള്‍ക്കുല്ല്ളില്‍'] - ][index]; + ['%s വര്‍ഷങ്ങള്‍ക്കു മുന്‍പ്', '%s വര്‍ഷങ്ങള്‍ക്കുല്ല്ളില്‍'], + ][index] as [string, string]; } diff --git a/src/lang/my.js b/src/lang/my.ts similarity index 89% rename from src/lang/my.js rename to src/lang/my.ts index 521180e..78db620 100644 --- a/src/lang/my.js +++ b/src/lang/my.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['ယခုအတွင်း', 'ယခု'], ['%s စက္ကန့် အကြာက', '%s စက္ကန့်အတွင်း'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 လ အကြာက', '1 လအတွင်း'], ['%s လ အကြာက', '%s လအတွင်း'], ['1 နှစ် အကြာက', '1 နှစ်အတွင်း'], - ['%s နှစ် အကြာက', '%s နှစ်အတွင်း'] - ][index]; + ['%s နှစ် အကြာက', '%s နှစ်အတွင်း'], + ][index] as [string, string]; } diff --git a/src/lang/nb_NO.js b/src/lang/nb_NO.ts similarity index 76% rename from src/lang/nb_NO.js rename to src/lang/nb_NO.ts index caf890a..2875aaf 100644 --- a/src/lang/nb_NO.js +++ b/src/lang/nb_NO.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['akkurat nå', 'om litt'], ['%s sekunder siden', 'om %s sekunder'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 måned siden', 'om 1 måned'], ['%s måneder siden', 'om %s måneder'], ['1 år siden', 'om 1 år'], - ['%s år siden', 'om %s år'] - ][index]; + ['%s år siden', 'om %s år'], + ][index] as [string, string]; } diff --git a/src/lang/nl.js b/src/lang/nl.ts similarity index 79% rename from src/lang/nl.js rename to src/lang/nl.ts index 30ba3a2..11b0968 100644 --- a/src/lang/nl.js +++ b/src/lang/nl.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['recent', 'binnenkort'], ['%s seconden geleden', 'binnen %s seconden'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 maand geleden', 'binnen 1 maand'], ['%s maanden geleden', 'binnen %s maanden'], ['1 jaar geleden', 'binnen 1 jaar'], - ['%s jaar geleden', 'binnen %s jaar'] - ][index]; + ['%s jaar geleden', 'binnen %s jaar'], + ][index] as [string, string]; } diff --git a/src/lang/nn_NO.js b/src/lang/nn_NO.ts similarity index 75% rename from src/lang/nn_NO.js rename to src/lang/nn_NO.ts index 6fc9e8c..d990294 100644 --- a/src/lang/nn_NO.js +++ b/src/lang/nn_NO.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['nett no', 'om litt'], ['%s sekund sidan', 'om %s sekund'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 månad sidan', 'om 1 månad'], ['%s månadar sidan', 'om %s månadar'], ['1 år sidan', 'om 1 år'], - ['%s år sidan', 'om %s år'] - ][index]; + ['%s år sidan', 'om %s år'], + ][index] as [string, string]; } diff --git a/src/lang/oc.js b/src/lang/oc.js deleted file mode 100644 index 27a80e2..0000000 --- a/src/lang/oc.js +++ /dev/null @@ -1,18 +0,0 @@ -export default function(number, index) { - return [ - ['fa un moment', 'd\'aquí un moment'], - ['fa %s segondas', 'd\'aquí %s segondas'], - ['fa 1 minuta', 'd\'aquí 1 minuta'], - ['fa %s minutas', 'd\'aquí %s minutas'], - ['fa 1 ora', 'd\'aquí 1 ora'], - ['fa %s oras', 'd\'aquí %s oras'], - ['fa 1 jorn', 'd\'aquí 1 jorn'], - ['fa %s jorns', 'd\'aquí %s jorns'], - ['fa 1 setmana', 'd\'aquí 1 setmana'], - ['fa %s setmanas', 'd\'aquí %s setmanas'], - ['fa 1 mes', 'd\'aquí 1 mes'], - ['fa %s meses', 'd\'aquí %s meses'], - ['fa 1 an', 'd\'aquí 1 an'], - ['fa %s ans', 'd\'aquí %s ans'] - ][index]; -} diff --git a/src/lang/oc.ts b/src/lang/oc.ts new file mode 100644 index 0000000..3e50295 --- /dev/null +++ b/src/lang/oc.ts @@ -0,0 +1,18 @@ +export default function(number: number, index: number): [string, string] { + return [ + ['fa un moment', "d'aquí un moment"], + ['fa %s segondas', "d'aquí %s segondas"], + ['fa 1 minuta', "d'aquí 1 minuta"], + ['fa %s minutas', "d'aquí %s minutas"], + ['fa 1 ora', "d'aquí 1 ora"], + ['fa %s oras', "d'aquí %s oras"], + ['fa 1 jorn', "d'aquí 1 jorn"], + ['fa %s jorns', "d'aquí %s jorns"], + ['fa 1 setmana', "d'aquí 1 setmana"], + ['fa %s setmanas', "d'aquí %s setmanas"], + ['fa 1 mes', "d'aquí 1 mes"], + ['fa %s meses', "d'aquí %s meses"], + ['fa 1 an', "d'aquí 1 an"], + ['fa %s ans', "d'aquí %s ans"], + ][index] as [string, string]; +} diff --git a/src/lang/pl.js b/src/lang/pl.ts similarity index 77% rename from src/lang/pl.js rename to src/lang/pl.ts index ca3edd0..65fa9f0 100644 --- a/src/lang/pl.js +++ b/src/lang/pl.ts @@ -1,8 +1,8 @@ // 0-13 alternately: single unit of time, // genitive plural form for all other numbers excluding cases below: -// 14-20: nominative plural form for the numbers 2,3,4 +// 14-20: nominative plural form for the numbers 2,3,4 // and all other numbers higher than 21 which end in 2,3,4 -var l = [ +const l = [ ['w tej chwili', 'za chwilę'], ['%s sekund temu', 'za %s sekund'], ['1 minutę temu', 'za 1 minutę'], @@ -23,12 +23,14 @@ var l = [ ['%s dni temu', 'za %s dni'], ['%s tygodnie temu', 'za %s tygodnie'], ['%s miesiące temu', 'za %s miesiące'], - ['%s lata temu', 'za %s lata'] + ['%s lata temu', 'za %s lata'], ]; -export default function(number, index) { +export default function(number: number, index: number): [string, string] { // to determine which plural form must be used check the last 2 digits // and calculate new index value to get the nominative form (14-20) // for all other cases use index value as it is (0-13) - return l[index&1?(number%10>4||number%10<2||1===~~(number/10)%10?index:++index/2+13):index]; -}; + return l[ + index & 1 ? (number % 10 > 4 || number % 10 < 2 || 1 === ~~(number / 10) % 10 ? index : ++index / 2 + 13) : index + ] as [string, string]; +} diff --git a/src/lang/pt_BR.js b/src/lang/pt_BR.ts similarity index 78% rename from src/lang/pt_BR.js rename to src/lang/pt_BR.ts index 412aacd..948e479 100644 --- a/src/lang/pt_BR.js +++ b/src/lang/pt_BR.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['agora mesmo', 'daqui um pouco'], ['há %s segundos', 'em %s segundos'], @@ -13,6 +13,6 @@ export default function(number, index) { ['há um mês', 'em um mês'], ['há %s meses', 'em %s meses'], ['há um ano', 'em um ano'], - ['há %s anos', 'em %s anos'] - ][index]; + ['há %s anos', 'em %s anos'], + ][index] as [string, string]; } diff --git a/src/lang/ro.js b/src/lang/ro.ts similarity index 70% rename from src/lang/ro.js rename to src/lang/ro.ts index a1061a5..623d8b7 100644 --- a/src/lang/ro.js +++ b/src/lang/ro.ts @@ -1,5 +1,5 @@ -export default function(number, index) { - var langTable = [ +export default function(number: number, index: number): [string, string] { + const langTable = [ ['chiar acum', 'chiar acum'], ['acum %s secunde', 'peste %s secunde'], ['acum un minut', 'peste un minut'], @@ -13,17 +13,14 @@ export default function(number, index) { ['acum o lună', 'peste o lună'], ['acum %s luni', 'peste %s luni'], ['acum un an', 'peste un an'], - ['acum %s ani', 'peste %s ani'] + ['acum %s ani', 'peste %s ani'], ]; if (number < 20) { - return langTable[index]; + return langTable[index] as [string, string]; } // A `de` preposition must be added between the number and the adverb // if the number is greater than 20. - return [ - langTable[index][0].replace('%s', '%s de'), - langTable[index][1].replace('%s', '%s de'), - ]; + return [langTable[index][0].replace('%s', '%s de'), langTable[index][1].replace('%s', '%s de')]; } diff --git a/src/lang/ru.js b/src/lang/ru.ts similarity index 50% rename from src/lang/ru.js rename to src/lang/ru.ts index 0917693..427ed01 100644 --- a/src/lang/ru.js +++ b/src/lang/ru.ts @@ -1,31 +1,3 @@ -var seconds = formatNum.bind(null, 'секунду', '%s секунду', '%s секунды', '%s секунд'), - minutes = formatNum.bind(null, 'минуту', '%s минуту', '%s минуты', '%s минут'), - hours = formatNum.bind(null, 'час', '%s час', '%s часа', '%s часов'), - days = formatNum.bind(null, 'день', '%s день', '%s дня', '%s дней'), - weeks = formatNum.bind(null, 'неделю', '%s неделю', '%s недели', '%s недель'), - months = formatNum.bind(null, 'месяц', '%s месяц', '%s месяца', '%s месяцев'), - years = formatNum.bind(null, 'год', '%s год', '%s года', '%s лет'); - -export default function(number, index) { - switch(index) { - case 0: return ['только что', 'через несколько секунд']; - case 1: return [seconds(number) + ' назад', 'через ' + seconds(number)]; - case 2: // ['минуту назад', 'через минуту']; - case 3: return [minutes(number) + ' назад', 'через ' + minutes(number)]; - case 4: // ['час назад', 'через час']; - case 5: return [hours(number) + ' назад', 'через ' + hours(number)]; - case 6: return ['вчера', 'завтра']; - case 7: return [days(number) + ' назад', 'через ' + days(number)]; - case 8: // ['неделю назад', 'через неделю']; - case 9: return [weeks(number) + ' назад', 'через ' + weeks(number)]; - case 10: // ['месяц назад', 'через месяц']; - case 11: return [months(number) + ' назад', 'через ' + months(number)]; - case 12: // ['год назад', 'через год']; - case 13: return [years(number) + ' назад', 'через ' + years(number)]; - default: return ['', ''] - } -}; - /** * * @param f1 - 1 @@ -33,11 +5,11 @@ export default function(number, index) { * @param s - 2-4, 22-24, 32-34 ... * @param t - 5-20, 25-30, ... * @param n - * @returns {string} + * @returns */ -function formatNum(f1, f, s, t, n) { - var n10 = n % 10, - str = t; +function formatNum(f1: string, f: string, s: string, t: string, n: number): string { + const n10 = n % 10; + let str = t; if (n === 1) { str = f1; @@ -46,6 +18,44 @@ function formatNum(f1, f, s, t, n) { } else if (n10 > 1 && n10 < 5 && (n > 20 || n < 10)) { str = s; } - + return str; } + +const seconds = formatNum.bind(null, 'секунду', '%s секунду', '%s секунды', '%s секунд'), + minutes = formatNum.bind(null, 'минуту', '%s минуту', '%s минуты', '%s минут'), + hours = formatNum.bind(null, 'час', '%s час', '%s часа', '%s часов'), + days = formatNum.bind(null, 'день', '%s день', '%s дня', '%s дней'), + weeks = formatNum.bind(null, 'неделю', '%s неделю', '%s недели', '%s недель'), + months = formatNum.bind(null, 'месяц', '%s месяц', '%s месяца', '%s месяцев'), + years = formatNum.bind(null, 'год', '%s год', '%s года', '%s лет'); + +export default function(number: number, index: number): [string, string] { + switch (index) { + case 0: + return ['только что', 'через несколько секунд']; + case 1: + return [seconds(number) + ' назад', 'через ' + seconds(number)]; + case 2: // ['минуту назад', 'через минуту']; + case 3: + return [minutes(number) + ' назад', 'через ' + minutes(number)]; + case 4: // ['час назад', 'через час']; + case 5: + return [hours(number) + ' назад', 'через ' + hours(number)]; + case 6: + return ['вчера', 'завтра']; + case 7: + return [days(number) + ' назад', 'через ' + days(number)]; + case 8: // ['неделю назад', 'через неделю']; + case 9: + return [weeks(number) + ' назад', 'через ' + weeks(number)]; + case 10: // ['месяц назад', 'через месяц']; + case 11: + return [months(number) + ' назад', 'через ' + months(number)]; + case 12: // ['год назад', 'через год']; + case 13: + return [years(number) + ' назад', 'через ' + years(number)]; + default: + return ['', '']; + } +} diff --git a/src/lang/sq.js b/src/lang/sq.ts similarity index 78% rename from src/lang/sq.js rename to src/lang/sq.ts index 89f7281..cd1d89a 100644 --- a/src/lang/sq.js +++ b/src/lang/sq.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['pak më parë', 'pas pak'], ['para %s sekondash', 'pas %s sekondash'], @@ -13,6 +13,6 @@ export default function(number, index) { ['para një muaji', 'pas një muaji'], ['para %s muajsh', 'pas %s muajsh'], ['para një viti', 'pas një viti'], - ['para %s vjetësh', 'pas %s vjetësh'] - ][index]; + ['para %s vjetësh', 'pas %s vjetësh'], + ][index] as [string, string]; } diff --git a/src/lang/sr.js b/src/lang/sr.js deleted file mode 100644 index 0c8587a..0000000 --- a/src/lang/sr.js +++ /dev/null @@ -1,42 +0,0 @@ -var seconds = formatNum.bind(null, '1 секунд', '%s секунд', '%s секунде', '%s секунди'), - minutes = formatNum.bind(null, '1 минут', '%s минут', '%s минуте', '%s минута'), - hours = formatNum.bind(null, 'сат времена', '%s сат', '%s сата', '%s сати'), - days = formatNum.bind(null, '1 дан', '%s дан', '%s дана', '%s дана'), - weeks = formatNum.bind(null, 'недељу дана', '%s недељу', '%s недеље', '%s недеља'), - months = formatNum.bind(null, 'месец дана', '%s месец', '%s месеца', '%s месеци'), - years = formatNum.bind(null, 'годину дана', '%s годину', '%s године', '%s година'); - -export default function(number, index) { - switch(index) { - case 0: return ['малопре', 'управо сад']; - case 1: return ['пре ' + seconds(number), 'за ' + seconds(number)]; - case 2: - case 3: return ['пре ' + minutes(number), 'за ' + minutes(number)]; - case 4: - case 5: return ['пре ' + hours(number), 'за ' + hours(number)]; - case 6: - case 7: return ['пре ' + days(number), 'за ' + days(number)]; - case 8: - case 9: return ['пре ' + weeks(number), 'за ' + weeks(number)]; - case 10: - case 11: return ['пре ' + months(number), 'за ' + months(number)]; - case 12: - case 13: return ['пре ' + years(number), 'за ' + years(number)]; - default: return ['', ''] - } -}; - -function formatNum(single, one, few, other, n) { - var rem10 = n % 10; - var rem100 = n % 100; - - if (n == 1) { - return single; - } else if (rem10 == 1 && rem100 != 11) { - return one; - } else if (rem10 >= 2 && rem10 <= 4 && !(rem100 >= 12 && rem100 <= 14)) { - return few; - } else { - return other; - } -} diff --git a/src/lang/sr.ts b/src/lang/sr.ts new file mode 100644 index 0000000..41fbf43 --- /dev/null +++ b/src/lang/sr.ts @@ -0,0 +1,51 @@ +function formatNum(single: string, one: string, few: string, other: string, n: number): string { + const rem10 = n % 10; + const rem100 = n % 100; + + if (n == 1) { + return single; + } else if (rem10 == 1 && rem100 != 11) { + return one; + } else if (rem10 >= 2 && rem10 <= 4 && !(rem100 >= 12 && rem100 <= 14)) { + return few; + } else { + return other; + } +} + +const seconds = formatNum.bind(null, '1 секунд', '%s секунд', '%s секунде', '%s секунди'), + minutes = formatNum.bind(null, '1 минут', '%s минут', '%s минуте', '%s минута'), + hours = formatNum.bind(null, 'сат времена', '%s сат', '%s сата', '%s сати'), + days = formatNum.bind(null, '1 дан', '%s дан', '%s дана', '%s дана'), + weeks = formatNum.bind(null, 'недељу дана', '%s недељу', '%s недеље', '%s недеља'), + months = formatNum.bind(null, 'месец дана', '%s месец', '%s месеца', '%s месеци'), + years = formatNum.bind(null, 'годину дана', '%s годину', '%s године', '%s година'); + +export default function(number: number, index: number): [string, string] { + switch (index) { + case 0: + return ['малопре', 'управо сад']; + case 1: + return ['пре ' + seconds(number), 'за ' + seconds(number)]; + case 2: + case 3: + return ['пре ' + minutes(number), 'за ' + minutes(number)]; + case 4: + case 5: + return ['пре ' + hours(number), 'за ' + hours(number)]; + case 6: + case 7: + return ['пре ' + days(number), 'за ' + days(number)]; + case 8: + case 9: + return ['пре ' + weeks(number), 'за ' + weeks(number)]; + case 10: + case 11: + return ['пре ' + months(number), 'за ' + months(number)]; + case 12: + case 13: + return ['пре ' + years(number), 'за ' + years(number)]; + default: + return ['', '']; + } +} diff --git a/src/lang/sv.js b/src/lang/sv.ts similarity index 78% rename from src/lang/sv.js rename to src/lang/sv.ts index f9f4f6d..1ffb9c4 100644 --- a/src/lang/sv.js +++ b/src/lang/sv.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['just nu', 'om en stund'], ['%s sekunder sedan', 'om %s sekunder'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 månad sedan', 'om 1 månad'], ['%s månader sedan', 'om %s månader'], ['1 år sedan', 'om 1 år'], - ['%s år sedan', 'om %s år'] - ][index]; + ['%s år sedan', 'om %s år'], + ][index] as [string, string]; } diff --git a/src/lang/ta.js b/src/lang/ta.ts similarity index 90% rename from src/lang/ta.js rename to src/lang/ta.ts index 32ecfcc..dbfa0ba 100644 --- a/src/lang/ta.js +++ b/src/lang/ta.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['இப்போது', 'சற்று நேரம் முன்பு'], ['%s நொடிக்கு முன்', '%s நொடிகளில்'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 மாதத்திற்கு முன்', '1 மாதத்தில்'], ['%s மாதங்களுக்கு முன்', '%s மாதங்களில்'], ['1 வருடத்திற்கு முன்', '1 வருடத்தில்'], - ['%s வருடங்களுக்கு முன்', '%s வருடங்களில்'] - ][index]; + ['%s வருடங்களுக்கு முன்', '%s வருடங்களில்'], + ][index] as [string, string]; } diff --git a/src/lang/th.js b/src/lang/th.ts similarity index 86% rename from src/lang/th.js rename to src/lang/th.ts index 9b5e7aa..29ed4d2 100644 --- a/src/lang/th.js +++ b/src/lang/th.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['เมื่อสักครู่นี้', 'อีกสักครู่'], ['%s วินาทีที่แล้ว', 'ใน %s วินาที'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 เดือนที่แล้ว', 'ใน 1 เดือน'], ['%s เดือนที่แล้ว', 'ใน %s เดือน'], ['1 ปีที่แล้ว', 'ใน 1 ปี'], - ['%s ปีที่แล้ว', 'ใน %s ปี'] - ][index]; + ['%s ปีที่แล้ว', 'ใน %s ปี'], + ][index] as [string, string]; } diff --git a/src/lang/tr.js b/src/lang/tr.ts similarity index 78% rename from src/lang/tr.js rename to src/lang/tr.ts index 1f7ed19..dbf3704 100644 --- a/src/lang/tr.js +++ b/src/lang/tr.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['az önce', 'şimdi'], ['%s saniye önce', '%s saniye içinde'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 ay önce', '1 ay içinde'], ['%s ay önce', '%s ay içinde'], ['1 yıl önce', '1 yıl içinde'], - ['%s yıl önce', '%s yıl içinde'] - ][index]; + ['%s yıl önce', '%s yıl içinde'], + ][index] as [string, string]; } diff --git a/src/lang/uk.js b/src/lang/uk.js deleted file mode 100644 index 5d0a1af..0000000 --- a/src/lang/uk.js +++ /dev/null @@ -1,41 +0,0 @@ -var seconds = formatNum.bind(null, 'секунду', '%s секунду', '%s секунди', '%s секунд'), - minutes = formatNum.bind(null, 'хвилину', '%s хвилину', '%s хвилини', '%s хвилин'), - hours = formatNum.bind(null, 'годину', '%s годину', '%s години', '%s годин'), - days = formatNum.bind(null, 'день', '%s день', '%s дні', '%s днів'), - weeks = formatNum.bind(null, 'тиждень', '%s тиждень', '%s тиждні', '%s тижднів'), - months = formatNum.bind(null, 'місяць', '%s місяць', '%s місяці', '%s місяців'), - years = formatNum.bind(null, 'рік', '%s рік', '%s роки', '%s років') - -export default function (number, index) { - switch (index) { - case 0: return ['щойно', 'через декілька секунд'] - case 1: return [seconds(number) + ' тому', 'через ' + seconds(number)] - case 2: - case 3: return [minutes(number) + ' тому', 'через ' + minutes(number)] - case 4: - case 5: return [hours(number) + ' тому', 'через ' + hours(number)] - case 6: - case 7: return [days(number) + ' тому', 'через ' + days(number)] - case 8: - case 9: return [weeks(number) + ' тому', 'через ' + weeks(number)] - case 10: - case 11: return [months(number) + ' тому', 'через ' + months(number)] - case 12: - case 13: return [years(number) + ' тому', 'через ' + years(number)] - default: return ['', ''] - } -} - -function formatNum(f1, f, s, t, n) { - var n10 = n % 10, - str = t - - if (n === 1) { - str = f1 - } else if (n10 === 1 && n > 20) { - str = f - } else if (n10 > 1 && n10 < 5 && (n > 20 || n < 10)) { - str = s - } - return str -} diff --git a/src/lang/uk.ts b/src/lang/uk.ts new file mode 100644 index 0000000..92cdc9f --- /dev/null +++ b/src/lang/uk.ts @@ -0,0 +1,50 @@ +function formatNum(f1: string, f: string, s: string, t: string, n: number): string { + const n10 = n % 10; + let str = t; + + if (n === 1) { + str = f1; + } else if (n10 === 1 && n > 20) { + str = f; + } else if (n10 > 1 && n10 < 5 && (n > 20 || n < 10)) { + str = s; + } + return str; +} + +const seconds = formatNum.bind(null, 'секунду', '%s секунду', '%s секунди', '%s секунд'), + minutes = formatNum.bind(null, 'хвилину', '%s хвилину', '%s хвилини', '%s хвилин'), + hours = formatNum.bind(null, 'годину', '%s годину', '%s години', '%s годин'), + days = formatNum.bind(null, 'день', '%s день', '%s дні', '%s днів'), + weeks = formatNum.bind(null, 'тиждень', '%s тиждень', '%s тиждні', '%s тижднів'), + months = formatNum.bind(null, 'місяць', '%s місяць', '%s місяці', '%s місяців'), + years = formatNum.bind(null, 'рік', '%s рік', '%s роки', '%s років'); + +export default function(number: number, index: number): [string, string] { + switch (index) { + case 0: + return ['щойно', 'через декілька секунд']; + case 1: + return [seconds(number) + ' тому', 'через ' + seconds(number)]; + case 2: + case 3: + return [minutes(number) + ' тому', 'через ' + minutes(number)]; + case 4: + case 5: + return [hours(number) + ' тому', 'через ' + hours(number)]; + case 6: + case 7: + return [days(number) + ' тому', 'через ' + days(number)]; + case 8: + case 9: + return [weeks(number) + ' тому', 'через ' + weeks(number)]; + case 10: + case 11: + return [months(number) + ' тому', 'через ' + months(number)]; + case 12: + case 13: + return [years(number) + ' тому', 'через ' + years(number)]; + default: + return ['', '']; + } +} diff --git a/src/lang/vi.js b/src/lang/vi.ts similarity index 79% rename from src/lang/vi.js rename to src/lang/vi.ts index 6e58cd3..601ed30 100644 --- a/src/lang/vi.js +++ b/src/lang/vi.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['vừa xong', 'một lúc'], ['%s giây trước', 'trong %s giây'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 tháng trước', 'trong 1 tháng'], ['%s tháng trước', 'trong %s tháng'], ['1 năm trước', 'trong 1 năm'], - ['%s năm trước', 'trong %s năm'] - ][index]; + ['%s năm trước', 'trong %s năm'], + ][index] as [string, string]; } diff --git a/src/lang/zh_CN.js b/src/lang/zh_CN.js deleted file mode 100644 index a86544d..0000000 --- a/src/lang/zh_CN.js +++ /dev/null @@ -1,18 +0,0 @@ -export default function(number, index) { - return [ - ['刚刚', '片刻后'], - ['%s 秒前', '%s 秒后'], - ['1 分钟前', '1 分钟后'], - ['%s 分钟前', '%s 分钟后'], - ['1 小时前', '1 小时后'], - ['%s 小时前', '%s 小时后'], - ['1 天前', '1 天后'], - ['%s 天前', '%s 天后'], - ['1 周前', '1 周后'], - ['%s 周前', '%s 周后'], - ['1 个月前', '1 个月后'], - ['%s 个月前', '%s 个月后'], - ['1 年前', '1 年后'], - ['%s 年前', '%s 年后'] - ][index]; -} diff --git a/src/lang/zh_CN.ts b/src/lang/zh_CN.ts new file mode 100644 index 0000000..bcfbd82 --- /dev/null +++ b/src/lang/zh_CN.ts @@ -0,0 +1,7 @@ +const ZH_CN = ['秒', '分钟', '小时', '天', '周', '个月', '年']; + +export default function(diff: number, idx: number): [string, string] { + if (idx === 0) return ['刚刚', '片刻后']; + const unit = ZH_CN[~~(idx / 2)]; + return [`${diff} ${unit}前`, `${diff} ${unit}后`]; +} diff --git a/src/lang/zh_TW.js b/src/lang/zh_TW.ts similarity index 76% rename from src/lang/zh_TW.js rename to src/lang/zh_TW.ts index bb215ca..7c15cf0 100644 --- a/src/lang/zh_TW.js +++ b/src/lang/zh_TW.ts @@ -1,4 +1,4 @@ -export default function(number, index) { +export default function(number: number, index: number): [string, string] { return [ ['剛剛', '片刻後'], ['%s 秒前', '%s 秒後'], @@ -13,6 +13,6 @@ export default function(number, index) { ['1 個月前', '1 個月後'], ['%s 個月前', '%s 個月後'], ['1 年前', '1 年後'], - ['%s 年前', '%s 年後'] - ][index]; + ['%s 年前', '%s 年後'], + ][index] as [string, string]; } diff --git a/src/locales.js b/src/locales.js deleted file mode 100644 index 3ea79e3..0000000 --- a/src/locales.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Created by hustcc on 18/5/20. - * Contract: i@hust.cc - */ - -const EN = 'second_minute_hour_day_week_month_year'.split('_'); -const ZH = '秒_分钟_小时_天_周_个月_年'.split('_'); - -const zh_CN = (number, index) => { - if (index === 0) return ['刚刚', '片刻后']; - const unit = ZH[parseInt(index / 2)]; - return [`${number} ${unit}前`, `${number} ${unit}后`]; -}; - -const en_US = (number, index) => { - if (index === 0) return ['just now', 'right now']; - let unit = EN[parseInt(index / 2)]; - if (number > 1) unit += 's'; - return [`${number} ${unit} ago`, `in ${number} ${unit}`]; -}; - -/** - * 所有的语言 - * @type {{en: function(*, *), zh_CN: function(*, *)}} - */ -const Locales = { - en_US, - zh_CN, -}; - -/** - * 注册语言 - * @param locale - * @param func - */ -export const register = (locale, func) => { - Locales[locale] = func; -}; - -/** - * 获取语言函数 - * @param locale - * @returns {*} - */ -export const getLocale = locale => { - return Locales[locale] || en_US; -}; diff --git a/src/locales.ts b/src/locales.ts new file mode 100644 index 0000000..39837c0 --- /dev/null +++ b/src/locales.ts @@ -0,0 +1,35 @@ +/** + * Created by hustcc on 18/5/20. + * Contract: i@hust.cc + */ + +import { LocaleFunc, LocaleMap } from './interface'; +import en_US from './lang/en_US'; +import zh_CN from './lang/zh_CN'; + +/** + * All locales supported. en_US, zh_CN is build-in + * @type {{en: function(*, *), zh_CN: function(*, *)}} + */ +const Locales: LocaleMap = { + en_US, + zh_CN, +}; + +/** + * register a locale + * @param locale + * @param func + */ +export const register = (locale: string, func: LocaleFunc) => { + Locales[locale] = func; +}; + +/** + * get a locale, default is en_US + * @param locale + * @returns {*} + */ +export const getLocale = (locale) => { + return Locales[locale] || en_US; +}; diff --git a/src/realtime.js b/src/realtime.js deleted file mode 100644 index 2ec2ba5..0000000 --- a/src/realtime.js +++ /dev/null @@ -1,54 +0,0 @@ -import { saveTimerId, getTimerId, getDateAttribute } from './utils/dom'; -import { formatDiff, diffSec, nextInterval } from './utils/date'; -import { getLocale } from './locales'; - -// 所有的 timer -const TimerPool = {}; - -const clear = tid => { - clearTimeout(tid); - delete TimerPool[tid]; -}; - -// 定时运行 -const run = (node, date, localeFunc, nowDate) => { - // 先清理掉之前的 - clear(getTimerId(node)); - - // get diff seconds - const diff = diffSec(date, nowDate); - // render - node.innerText = formatDiff(diff, localeFunc); - - const tid = setTimeout(() => { - run(node, date, localeFunc, nowDate); - }, nextInterval(diff) * 1000, 0x7FFFFFFF); - - // there is no need to save node in object. Just save the key - TimerPool[tid] = 0; - saveTimerId(node, tid); -}; - -// 取消一个 node 的实时渲染 -export const cancel = node => { - if (node) clear(getTimerId(node)); // get the timer of DOM node(native / jq). - else for (const tid in TimerPool) clear(tid); -}; - -// 实时渲染一系列节点 -export const render = (nodes, locale, nowDate) => { - // by .length - if (nodes.length === undefined) nodes = [nodes]; - - let node; - for (let i = 0; i < nodes.length; i ++) { - node = nodes[i]; - - const date = getDateAttribute(node); - const localeFunc = getLocale(locale); - run(node, date, localeFunc, nowDate); - } - - return nodes; -}; - diff --git a/src/realtime.ts b/src/realtime.ts new file mode 100644 index 0000000..432e9e6 --- /dev/null +++ b/src/realtime.ts @@ -0,0 +1,60 @@ +import { setTimerId, getTimerId, getDateAttribute } from './utils/dom'; +import { formatDiff, diffSec, nextInterval } from './utils/date'; +import { getLocale } from './locales'; +import { TDate, TimerPool } from './interface'; + +// all realtime timer +const TIMER_POOL: TimerPool = {}; + +/** + * clear a timer from pool + * @param tid + */ +const clear = (tid: number): void => { + clearTimeout(tid); + delete TIMER_POOL[tid]; +}; + +// run with timer(setTimeout) +function run(node: HTMLElement, date, localeFunc, nowDate): void { + // clear the node's exist timer + clear(getTimerId(node)); + + // get diff seconds + const diff = diffSec(date, nowDate); + // render + node.innerText = formatDiff(diff, localeFunc); + + const tid = (setTimeout( + () => { + run(node, date, localeFunc, nowDate); + }, + nextInterval(diff) * 1000, + 0x7fffffff, + ) as unknown) as number; + + // there is no need to save node in object. Just save the key + TIMER_POOL[tid] = 0; + setTimerId(node, tid); +} + +// 取消一个 node 的实时渲染 +export function cancel(node?: HTMLElement): void { + // cancel one + if (node) clear(getTimerId(node)); + // cancel all + // @ts-ignore + else Object.keys(TIMER_POOL).forEach(clear); +} + +// 实时渲染一系列节点 +export const render = (nodes: HTMLElement | NodeList, locale?: string, relativeDate?: TDate) => { + // by .length + const nodeList: NodeList = 'length' in nodes ? nodes : (([nodes] as unknown) as NodeList); + + nodeList.forEach((node: HTMLElement) => { + run(node, getDateAttribute(node), getLocale(locale), relativeDate); + }); + + return nodeList; +}; diff --git a/src/utils/date.js b/src/utils/date.js deleted file mode 100644 index 935cd63..0000000 --- a/src/utils/date.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Created by hustcc on 18/5/20. - * Contract: i@hust.cc - */ - -const SEC_ARRAY = [60, 60, 24, 7, 365/7/12, 12]; - -/** - * change f into int, remove decimal. Just for code compression - * @param f - * @returns {number} - */ -export const toInt = f => parseInt(f); - -/** - * format Date / string / timestamp to Date instance. - * @param input - * @returns {*} - */ -export const toDate = input => { - if (input instanceof Date) return input; - if (!isNaN(input) || /^\d+$/.test(input)) return new Date(toInt(input)); - input = (input || '').trim().replace(/\.\d+/, '') // remove milliseconds - .replace(/-/, '/').replace(/-/, '/') - .replace(/(\d)T(\d)/, '$1 $2').replace(/Z/, ' UTC') // 2017-2-5T3:57:52Z -> 2017-2-5 3:57:52UTC - .replace(/([\+\-]\d\d)\:?(\d\d)/, ' $1$2'); // -04:00 -> -0400 - return new Date(input); -}; - -/** - * format the diff second to *** time ago, with setting locale - * @param diff - * @param localeFunc - * @returns {string | void | *} - */ -export const formatDiff = (diff, localeFunc) => { - // if locale is not exist, use defaultLocale. - // if defaultLocale is not exist, use build-in `en`. - // be sure of no error when locale is not exist. - let i = 0, - agoin = diff < 0 ? 1 : 0, // timein or timeago - total_sec = diff = Math.abs(diff); - - for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY.length; i++) { - diff /= SEC_ARRAY[i]; - } - diff = toInt(diff); - i *= 2; - - if (diff > (i === 0 ? 9 : 1)) i += 1; - return localeFunc(diff, i, total_sec)[agoin].replace('%s', diff); -}; - -/** - * calculate the diff second between date to be formatted an now date. - * @param date - * @param nowDate - * @returns {number} - */ -export const diffSec = (date, nowDate) => { - nowDate = nowDate ? toDate(nowDate) : new Date(); - return (nowDate - toDate(date)) / 1000; -}; - -/** - * nextInterval: calculate the next interval time. - * - diff: the diff sec between now and date to be formatted. - * - * What's the meaning? - * diff = 61 then return 59 - * diff = 3601 (an hour + 1 second), then return 3599 - * make the interval with high performance. - **/ -export const nextInterval = diff => { - let rst = 1, i = 0, d = Math.abs(diff); - for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY.length; i ++) { - diff /= SEC_ARRAY[i]; - rst *= SEC_ARRAY[i]; - } - d = d % rst; - d = d ? rst - d : rst; - return Math.ceil(d); -}; diff --git a/src/utils/date.ts b/src/utils/date.ts new file mode 100644 index 0000000..0c94869 --- /dev/null +++ b/src/utils/date.ts @@ -0,0 +1,91 @@ +/** + * Created by hustcc on 18/5/20. + * Contract: i@hust.cc + */ + +import { LocaleFunc, TDate } from '../interface'; + +const SEC_ARRAY = [60, 60, 24, 7, 365 / 7 / 12, 12]; + +/** + * format Date / string / timestamp to Date instance. + * @param input + * @returns {*} + */ +export function toDate(input?: Date | string | number): number { + if (input instanceof Date) return +input; + // @ts-ignore + if (!isNaN(input) || /^\d+$/.test(input)) return +new Date(parseInt(input)); + input = (input || '') + // @ts-ignore + .trim() + .replace(/\.\d+/, '') // remove milliseconds + .replace(/-/, '/') + .replace(/-/, '/') + .replace(/(\d)T(\d)/, '$1 $2') + .replace(/Z/, ' UTC') // 2017-2-5T3:57:52Z -> 2017-2-5 3:57:52UTC + .replace(/([+-]\d\d):?(\d\d)/, ' $1$2'); // -04:00 -> -0400 + return +new Date(input); +} + +/** + * format the diff second to *** time ago, with setting locale + * @param diff + * @param localeFunc + * @returns + */ +export function formatDiff(diff: number, localeFunc: LocaleFunc): string { + // if locale is not exist, use defaultLocale. + // if defaultLocale is not exist, use build-in `en`. + // be sure of no error when locale is not exist. + const agoIn = diff < 0 ? 1 : 0; // time in or time ago + + diff = Math.abs(diff); + const totalSec = diff; + + let idx = 0; + + for (; diff >= SEC_ARRAY[idx] && idx < SEC_ARRAY.length; idx++) { + diff /= SEC_ARRAY[idx]; + } + diff = ~~diff; + idx *= 2; + + if (diff > (idx === 0 ? 9 : 1)) idx += 1; + // @ts-ignore + return localeFunc(diff, idx, totalSec)[agoIn].replace('%s', diff); +} + +/** + * calculate the diff second between date to be formatted an now date. + * @param date + * @param nowDate + * @returns + */ +export function diffSec(date: TDate, nowDate?: TDate): number { + nowDate = nowDate ? toDate(nowDate) : +new Date(); + return (nowDate - toDate(date)) / 1000; +} + +/** + * nextInterval: calculate the next interval time. + * - diff: the diff sec between now and date to be formatted. + * + * What's the meaning? + * diff = 61 then return 59 + * diff = 3601 (an hour + 1 second), then return 3599 + * make the interval with high performance. + **/ +export function nextInterval(diff: number): number { + let rst = 1, + i = 0, + d = Math.abs(diff); + for (; diff >= SEC_ARRAY[i] && i < SEC_ARRAY.length; i++) { + diff /= SEC_ARRAY[i]; + rst *= SEC_ARRAY[i]; + } + d = d % rst; + d = d ? rst - d : rst; + // Math.ceil + return ~~d; +} diff --git a/src/utils/dom.js b/src/utils/dom.js deleted file mode 100644 index 45e823c..0000000 --- a/src/utils/dom.js +++ /dev/null @@ -1,33 +0,0 @@ -const ATTR_TIMEAGO_TID = 'timeago-tid'; -const ATTR_DATETIME = 'datetime'; - -/** - * get the node attribute, native DOM and jquery supported. - * @param node - * @param name - * @returns {*} - */ -const getAttribute = (node, name) => { - if (node.getAttribute) return node.getAttribute(name); // native dom - if (node.attr) return node.attr(name); // jquery dom -}; - -/** - * get the datetime attribute, `data-timeagp` / `datetime` are supported. - * @param node - * @returns {*} - */ -export const getDateAttribute = node => getAttribute(node, ATTR_DATETIME); - -/** - * set the node attribute, native DOM and jquery supported. - * @param node - * @param timerId - * @returns {*} - */ -export const saveTimerId = (node, timerId) => { - if (node.setAttribute) return node.setAttribute(ATTR_TIMEAGO_TID, timerId); - if (node.attr) return node.attr(ATTR_TIMEAGO_TID, timerId); -}; - -export const getTimerId = node => getAttribute(node, ATTR_TIMEAGO_TID); diff --git a/src/utils/dom.ts b/src/utils/dom.ts new file mode 100644 index 0000000..a77b77d --- /dev/null +++ b/src/utils/dom.ts @@ -0,0 +1,30 @@ +const ATTR_TIMEAGO_TID = 'timeago-tid'; +const ATTR_DATETIME = 'datetime'; + +/** + * get the datetime attribute, `datetime` are supported. + * @param node + * @returns {*} + */ +export function getDateAttribute(node: HTMLElement): string { + return node.getAttribute(ATTR_DATETIME); +} + +/** + * set the node attribute, native DOM + * @param node + * @param timerId + * @returns {*} + */ +export function setTimerId(node: HTMLElement, timerId: number): void { + // @ts-ignore + node.setAttribute(ATTR_TIMEAGO_TID, timerId); +} + +/** + * get the timer id + * @param node + */ +export function getTimerId(node: HTMLElement): number { + return ~~node.getAttribute(ATTR_TIMEAGO_TID); +} diff --git a/timeago.d.ts b/timeago.d.ts deleted file mode 100644 index 6811b51..0000000 --- a/timeago.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -/// -type TDate = Date | string | number; - -export declare function format(date: TDate, locale?: string, relativeDate?: TDate): string; -export declare function render(nodes: Node | NodeList | JQuery, locale?: string, relativeDate?: TDate): void; -export declare function cancel(node?: Node | JQuery): void; -export declare function register(locale: string, localeFunc: Function): void; diff --git a/tsconfig.ci.json b/tsconfig.ci.json new file mode 100644 index 0000000..2b85b59 --- /dev/null +++ b/tsconfig.ci.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "outDir": "lib", + "module": "commonjs", + "target": "es5", + "jsx": "preserve", + "moduleResolution": "node", + "experimentalDecorators": true, + "declaration": true, + "sourceMap": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "pretty": true, + "lib": ["dom", "esnext"], + "skipLibCheck": true, + "sourceRoot": "src", + "baseUrl": "src" + }, + "include": ["src/**/*", "__tests__/**/*"], + "exclude": ["node_modules"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d61bc11 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "outDir": "lib", + "module": "commonjs", + "target": "es5", + "jsx": "preserve", + "moduleResolution": "node", + "experimentalDecorators": true, + "declaration": true, + "sourceMap": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "pretty": true, + "lib": ["dom", "esnext"], + "skipLibCheck": true, + "sourceRoot": "src", + "baseUrl": "src" + }, + "include": ["src/**/*"], + "exclude": ["node_modules"] +}