├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── nodejs.yml ├── .gitignore ├── .prettierrc ├── CHANGELOG-OLD.md ├── LICENSE ├── README.md ├── bili.config.ts ├── example ├── AutoUpdate.vue ├── BasicUsage.vue ├── CustomConverter.vue ├── app.vue ├── index.js ├── style.css └── vue-readme-loader.js ├── package.json ├── poi.config.js ├── src ├── converter.js └── index.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [master] 9 | pull_request: 10 | branches: [master] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [14.x] 19 | 20 | steps: 21 | - uses: actions/checkout@v2 22 | - name: Use Node.js ${{ matrix.node-version }} 23 | uses: actions/setup-node@v1 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | - run: yarn 27 | - run: npm run test --if-present 28 | - run: npx semantic-release 29 | env: 30 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 31 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .DS_Store 4 | /index.js 5 | /index.umd.js 6 | dist 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /CHANGELOG-OLD.md: -------------------------------------------------------------------------------- 1 | ## [Version 5.0.0](https://github.com/egoist/vue-timeago/releases/tag/v5.0.0) (2018-7-22) 2 | 3 | ### Breaking changes 4 | 5 | - support custom converter: [`03141bd`](https://github.com/egoist/vue-timeago/commit/03141bd) 6 | 7 | [...full changes](https://github.com/egoist/vue-timeago/compare/v4.0.2...v5.0.0) 8 | 9 | ## [Version 4.0.2](https://github.com/egoist/vue-timeago/releases/tag/v4.0.2) (2018-6-7) 10 | 11 | ### Bug fixes 12 | 13 | - update `timeago` when `since` changed, fixed [#79](https://github.com/egoist/vue-timeago/issues/79): [`275366c`](https://github.com/egoist/vue-timeago/commit/275366c) 14 | 15 | [...full changes](https://github.com/egoist/vue-timeago/compare/v4.0.1...v4.0.2) 16 | 17 | ## [Version 4.0.1](https://github.com/egoist/vue-timeago/releases/tag/v4.0.1) (2018-5-11) 18 | 19 | ### Bug fixes 20 | 21 | - tweaks: [`cbeb9b9`](https://github.com/egoist/vue-timeago/commit/cbeb9b9) 22 | - require date-fns as peerDependency: [`f9e86ce`](https://github.com/egoist/vue-timeago/commit/f9e86ce) 23 | 24 | [...full changes](https://github.com/egoist/vue-timeago/compare/v4.0.0...v4.0.1) 25 | 26 | ## [Version 4.0.0](https://github.com/egoist/vue-timeago/releases/tag/v4.0.0) (2018-5-11) 27 | 28 | ### Breaking changes 29 | 30 | - use date-fns: [`f404920`](https://github.com/egoist/vue-timeago/commit/f404920) 31 | 32 | ### Bug fixes 33 | 34 | - tweaks: [`7e21ecb`](https://github.com/egoist/vue-timeago/commit/7e21ecb) 35 | 36 | [...full changes](https://github.com/egoist/vue-timeago/compare/v3.4.4...v4.0.0) 37 | 38 | ## [Version 3.4.4](https://github.com/egoist/vue-timeago/releases/tag/v3.4.4) (2018-2-19) 39 | 40 | ### Bug fixes 41 | 42 | - Update ar-SA.json: [`bcb2b0e`](https://github.com/egoist/vue-timeago/commit/bcb2b0e) ([#71](https://github.com/egoist/vue-timeago/issues/71)) 43 | 44 | [...full changes](https://github.com/egoist/vue-timeago/compare/v3.4.3...v3.4.4) 45 | 46 | ## [Version 3.4.3](https://github.com/egoist/vue-timeago/releases/tag/v3.4.3) (2018-2-17) 47 | 48 | ### Bug fixes 49 | 50 | - Update nl-NL.json: [`21434aa`](https://github.com/egoist/vue-timeago/commit/21434aa) ([#67](https://github.com/egoist/vue-timeago/issues/67)) 51 | - Create ar-SA.json: [`f8d4eac`](https://github.com/egoist/vue-timeago/commit/f8d4eac) ([#69](https://github.com/egoist/vue-timeago/issues/69)) 52 | 53 | [...full changes](https://github.com/egoist/vue-timeago/compare/v3.4.2...v3.4.3) 54 | 55 | ## [Version 3.4.2](https://github.com/egoist/vue-timeago/releases/tag/v3.4.2) (2017-12-14) 56 | 57 | ### Bug fixes 58 | 59 | - Corrected display direction for the hebrew (he-IL) locale.: [`293f793`](https://github.com/egoist/vue-timeago/commit/293f793) ([#61](https://github.com/egoist/vue-timeago/issues/61)) 60 | - Fixed 'sort of' grammar error: [`fc740ad`](https://github.com/egoist/vue-timeago/commit/fc740ad) ([#48](https://github.com/egoist/vue-timeago/issues/48)) 61 | - Korean Translation.: [`615caa5`](https://github.com/egoist/vue-timeago/commit/615caa5) ([#63](https://github.com/egoist/vue-timeago/issues/63)) 62 | - Croatian translation: [`44c814a`](https://github.com/egoist/vue-timeago/commit/44c814a) ([#62](https://github.com/egoist/vue-timeago/issues/62)) 63 | 64 | [...full changes](https://github.com/egoist/vue-timeago/compare/v3.4.1...v3.4.2) 65 | 66 | ## [Version 3.4.1](https://github.com/egoist/vue-timeago/releases/tag/v3.4.1) (2017-12-2) 67 | 68 | ### Bug fixes 69 | 70 | - Add hebrew locale: [`ff8ccb4`](https://github.com/egoist/vue-timeago/commit/ff8ccb4) ([#60](https://github.com/egoist/vue-timeago/issues/60)) 71 | 72 | [...full changes](https://github.com/egoist/vue-timeago/compare/v3.4.0...v3.4.1) 73 | 74 | ## [Version 3.4.0](https://github.com/egoist/vue-timeago/releases/tag/v3.4.0) (2017-10-27) 75 | 76 | ### New features 77 | 78 | - Show actual time in title while maxTime has not passed: [`575d6cc`](https://github.com/egoist/vue-timeago/commit/575d6cc) ([#57](https://github.com/egoist/vue-timeago/issues/57)) 79 | 80 | ### Bug fixes 81 | 82 | - fix typo in Vietnamese: [`f5c71dc`](https://github.com/egoist/vue-timeago/commit/f5c71dc) ([#58](https://github.com/egoist/vue-timeago/issues/58)) 83 | - Add Estonian translation: [`3921a93`](https://github.com/egoist/vue-timeago/commit/3921a93) ([#59](https://github.com/egoist/vue-timeago/issues/59)) 84 | 85 | [...full changes](https://github.com/egoist/vue-timeago/compare/v3.3.6...v3.4.0) 86 | 87 | ## [Version 3.1.5](https://github.com/egoist/vue-timeago/releases/tag/v3.1.5) (2017-1-4) 88 | 89 | ### Patches 90 | 91 | - build before publish: [`0f4aed0`](https://github.com/egoist/vue-timeago/commit/0f4aed0) 92 | 93 | [...full changes](https://github.com/egoist/vue-timeago/compare/v3.1.4...v3.1.5) 94 | 95 | ## [Version 3.1.4](https://github.com/egoist/vue-timeago/releases/tag/v3.1.4) (2017-1-4) 96 | 97 | ### Patches 98 | 99 | - Add Vietnamese locale: [`1143ccb`](https://github.com/egoist/vue-timeago/commit/1143ccb) ([#35](https://github.com/egoist/vue-timeago/issues/35)) 100 | - Add Indonesian locale: [`79ec271`](https://github.com/egoist/vue-timeago/commit/79ec271) ([#36](https://github.com/egoist/vue-timeago/issues/36)) 101 | 102 | [...full changes](https://github.com/egoist/vue-timeago/compare/v3.1.3...v3.1.4) 103 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) EGOIST <0x142857@gmail.com> (github.com/egoist) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-timeago [![NPM version](https://img.shields.io/npm/v/vue-timeago.svg)](https://npmjs.com/package/vue-timeago) [![NPM downloads](https://img.shields.io/npm/dm/vue-timeago.svg)](https://npmjs.com/package/vue-timeago) [![Build Status](https://img.shields.io/circleci/project/github/egoist/vue-timeago/master.svg)](https://circleci.com/gh/egoist/vue-timeago) 2 | 3 | > A timeago component Vue.js 4 | 5 | ## Install 6 | 7 | ```bash 8 | yarn add vue-timeago 9 | # or 10 | npm i vue-timeago 11 | ``` 12 | 13 | CDN: [UNPKG](https://unpkg.com/vue-timeago/dist/) | [jsDelivr](https://cdn.jsdelivr.net/npm/vue-timeago/dist/) (available as `window.VueTimeago`) 14 | 15 | ## Usage 16 | 17 | For usages on version 4, please check out [this branch](https://github.com/egoist/vue-timeago/tree/4). 18 | 19 | ```js 20 | import VueTimeago from 'vue-timeago' 21 | 22 | Vue.use(VueTimeago, { 23 | name: 'Timeago', // Component name, `Timeago` by default 24 | locale: 'en', // Default locale 25 | // We use `date-fns` under the hood 26 | // So you can use all locales from it 27 | locales: { 28 | 'zh-CN': require('date-fns/locale/zh_cn'), 29 | ja: require('date-fns/locale/ja') 30 | } 31 | }) 32 | ``` 33 | 34 | Then in your lovely component: 35 | 36 | ```vue 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ``` 48 | 49 | ## Plugin options 50 | 51 | ```js 52 | Vue.use(VueTimeago, pluginOptions) 53 | ``` 54 | 55 | ### locales 56 | 57 | - **Type**: `{ [localeName: string]: any }` 58 | 59 | An object of locales. 60 | 61 | ### locale 62 | 63 | - **Type**: `string` 64 | 65 | The default locale name. 66 | 67 | ### converter 68 | 69 | - **Type**: `(date, locale, converterOptions) => string` 70 | 71 | A `converter` that formats regular dates in `xxx ago` or `in xxx` style. 72 | 73 | Check out our [default converter](https://github.com/egoist/vue-timeago/blob/master/src/converter.js) which uses [date-fns/distance_in_words_to_now](https://date-fns.org/v1.29.0/docs/distanceInWordsToNow) under the hood. 74 | 75 | ### converterOptions 76 | 77 | - **Type**: `Object` 78 | 79 | Provide an object which will be available as argument `converterOptions` in the `converter` we mentioned above. 80 | 81 | Our default converter supports most options that [date-fns/distance_in_words_to_now](https://date-fns.org/v1.29.0/docs/distanceInWordsToNow) library supports, namely: 82 | 83 | - **includeSeconds**: (default: `false`) distances less than a minute are more detailed 84 | - **addSuffix**: (default: `true`) result specifies if the second date is earlier or later than the first 85 | 86 | ## props 87 | 88 | ### datetime 89 | 90 | - **Type**: `Date` `string` `number` 91 | - **Required**: `true` 92 | 93 | The datetime to be formatted . 94 | 95 | ### autoUpdate 96 | 97 | - **Type**: `number` `boolean` 98 | - **Default**: `false` 99 | 100 | The period to update the component, in **seconds**. 101 | 102 | You can omit this prop or set it to `0` or `false` to disable auto-update. 103 | 104 | When `true` it will be equivalent to `60`. 105 | 106 | ### locale 107 | 108 | Just like the `locale` option in the plugin options, but this could override the global one. 109 | 110 | ### converter 111 | 112 | Just like the `converter` option in the plugin options, but this could override the global one. 113 | 114 | ### converterOptions 115 | 116 | Just like the `converterOptions` option in the plugin options, but this could override the global one. 117 | 118 | ## Recipes 119 | 120 | ### Update Locale Globally 121 | 122 | ```js 123 | Vue.use(VueTimeago, { 124 | locale: 'en', 125 | locales: { 126 | 'zh-CN': require('date-fns/locale/zh_cn') 127 | } 128 | }) 129 | ``` 130 | 131 | In your components you can use `this.$timeago.locale` to access the global locale, in this case it's `en`, the `` component will get updated when you set it to another valid locale, e.g. `this.$timeago.locale = 'zh-CN'`. 132 | 133 | ## What about the good old [vue-timeago v3](https://github.com/egoist/vue-timeago/tree/3)? 134 | 135 | The older version (700 bytes gzipped) is much smaller than the current version (2.8kB gzipped) that uses [`date-fns`](https://date-fns.org/). 136 | 137 | But the current version gives more precise result (and hopefully handles more edge cases), and we don't need to maintain a big list of locale messages because `date-fns` already did it for us. 138 | 139 | ## Development 140 | 141 | ```bash 142 | # for dev 143 | yarn example 144 | 145 | # build in cjs es umd format 146 | yarn build 147 | ``` 148 | 149 | ## License 150 | 151 | MIT © [EGOIST](https://github.com/egoist) 152 | -------------------------------------------------------------------------------- /bili.config.ts: -------------------------------------------------------------------------------- 1 | import { Config } from 'bili' 2 | 3 | const config: Config = { 4 | input: 'src/index.js', 5 | output: { 6 | moduleName: 'VueTimeago', 7 | format: ['esm', 'umd', 'cjs'], 8 | fileName({ format }, defaultFileName) { 9 | if (format === 'cjs') { 10 | return 'vue-timeago.cjs.js' 11 | } 12 | if (format === 'umd') { 13 | return 'vue-timeago.js' 14 | } 15 | if (format === 'esm') { 16 | return 'vue-timeago.es.js' 17 | } 18 | return defaultFileName 19 | }, 20 | sourceMapExcludeSources: true 21 | }, 22 | babel: { 23 | minimal: true 24 | }, 25 | extendConfig(config, { format }) { 26 | if (format === 'umd') { 27 | config.output.minify = true 28 | config.env = Object.assign({}, config.env, { 29 | NODE_ENV: 'production' 30 | }) 31 | } 32 | return config 33 | } 34 | } 35 | 36 | export default config 37 | -------------------------------------------------------------------------------- /example/AutoUpdate.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | 22 | 23 | Code used by this demo: 24 | 25 | ```html 26 | 31 | ``` 32 | 33 | You can use `autoUpdate` prop to control how often this component should be updated, for example if you set it to `true`, it will be updated every 60 seconds. 34 | 35 | -------------------------------------------------------------------------------- /example/BasicUsage.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 21 | 22 | 23 | First you need to use the plugin: 24 | 25 | ```js 26 | import Timeago from 'vue-timeago' 27 | 28 | Vue.use(Timeago) 29 | ``` 30 | 31 | Then use the `` component in your Vue component like this: 32 | 33 | ```html 34 | 39 | 40 | 49 | ``` 50 | 51 | -------------------------------------------------------------------------------- /example/CustomConverter.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 27 | 28 | 29 | You can use a custom converter to control how machine time is converted to human-readable time: 30 | 31 | ```html 32 | 35 | 36 | 50 | ``` 51 | 52 | -------------------------------------------------------------------------------- /example/app.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 39 | 40 | 45 | 46 | 56 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import './style.css' 2 | import Vue from 'vue' 3 | import { create, mount } from 'demoboard' 4 | import toReact from '@egoist/vue-to-react' 5 | import Timeago from '../src' 6 | import converter from '../src/converter' 7 | import BasicUsage from './BasicUsage.vue' 8 | import AutoUpdate from './AutoUpdate.vue' 9 | import CustomConverter from './CustomConverter.vue' 10 | import readme from '!raw-loader!../README.md' 11 | 12 | const r = require.context('date-fns/locale', true, /^\.\/([\w\_]+)\/index\.js/) 13 | const locales = {} 14 | r.keys().forEach(v => { 15 | const [, name] = /^\.\/([\w\_]+)\/index\.js/.exec(v) 16 | locales[name] = r(v) 17 | }) 18 | 19 | Vue.use(Timeago, { 20 | locale: 'en', 21 | locales, 22 | converter 23 | }) 24 | 25 | const demoboard = create() 26 | 27 | demoboard.section('Examples').add('Basic Usage', { 28 | component: toReact(BasicUsage), 29 | readme: BasicUsage.$readme, 30 | code: BasicUsage.$code 31 | }).add('Auto Update', { 32 | component: toReact(AutoUpdate), 33 | readme: AutoUpdate.$readme, 34 | code: AutoUpdate.$code 35 | }).add('Custom Converter', { 36 | component: toReact(CustomConverter), 37 | readme: CustomConverter.$readme, 38 | code: CustomConverter.$code 39 | }) 40 | 41 | mount(demoboard, '#app', { 42 | title: 'Vue Timeago', 43 | readme 44 | }) 45 | -------------------------------------------------------------------------------- /example/style.css: -------------------------------------------------------------------------------- 1 | .box { 2 | border: 1px solid #e2e2e2; 3 | border-radius: 3px; 4 | padding: 20px; 5 | position: relative; 6 | margin-bottom: 20px; 7 | max-width: 800px; 8 | } 9 | 10 | .box:before { 11 | display: block; 12 | content: attr(data-title); 13 | position: absolute; 14 | top: 0; 15 | left: 20px; 16 | transform: translateY(-50%); 17 | background: white; 18 | color: #999; 19 | padding: 0 5px; 20 | font-size: 14px; 21 | } 22 | -------------------------------------------------------------------------------- /example/vue-readme-loader.js: -------------------------------------------------------------------------------- 1 | module.exports = source => { 2 | return `export default function (Component) { 3 | Component.options.$readme = ${JSON.stringify(source.trim())} 4 | }` 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-timeago", 3 | "version": "5.0.0", 4 | "productName": "Vue Timeago", 5 | "description": "A timeago filter for Vue.", 6 | "license": "MIT", 7 | "repository": "egoist/vue-timeago", 8 | "author": { 9 | "name": "EGOIST", 10 | "email": "0x142857@gmail.com", 11 | "url": "https://github.com/egoist" 12 | }, 13 | "scripts": { 14 | "test": "xo && npm run build", 15 | "build": "bili", 16 | "prepublishOnly": "npm run build", 17 | "example": "poi example/index.js -so" 18 | }, 19 | "main": "dist/vue-timeago.cjs.js", 20 | "module": "dist/vue-timeago.es.js", 21 | "unpkg": "dist/vue-timeago.js", 22 | "jsdelivr": "dist/vue-timeago.js", 23 | "cdn": "dist/vue-timeago.js", 24 | "files": [ 25 | "dist" 26 | ], 27 | "keywords": [ 28 | "timeago", 29 | "vue", 30 | "filter" 31 | ], 32 | "devDependencies": { 33 | "@egoist/vue-to-react": "^1.1.0", 34 | "bili": "^4.7.0", 35 | "commitizen": "^3.0.7", 36 | "cz-conventional-changelog": "^2.1.0", 37 | "demoboard": "^0.3.1", 38 | "eslint-config-prettier": "^4.1.0", 39 | "eslint-config-rem": "^4.0.0", 40 | "eslint-plugin-prettier": "^3.0.1", 41 | "gh-pages": "^1.0.0", 42 | "husky": "^1.3.1", 43 | "lint-staged": "^8.1.5", 44 | "poi": "^12.10.3", 45 | "postcss-nested": "^4.1.2", 46 | "prettier": "^1.16.4", 47 | "raw-loader": "^3.0.0", 48 | "semantic-release": "^17.3.6", 49 | "vue": "^2.6.9", 50 | "vue-template-compiler": "^2.6.9", 51 | "xo": "^0.24.0" 52 | }, 53 | "xo": { 54 | "extends": [ 55 | "rem", 56 | "plugin:prettier/recommended" 57 | ], 58 | "ignores": [ 59 | "example/**" 60 | ] 61 | }, 62 | "dependencies": { 63 | "date-fns": "^1.29.0" 64 | }, 65 | "husky": { 66 | "hooks": { 67 | "pre-commit": "lint-staged" 68 | } 69 | }, 70 | "lint-staged": { 71 | "*.{ts,json,md}": [ 72 | "prettier --write", 73 | "git add" 74 | ], 75 | "src/*.js": [ 76 | "xo --fix", 77 | "git add" 78 | ] 79 | }, 80 | "release": { 81 | "branch": "master" 82 | }, 83 | "config": { 84 | "commitizen": { 85 | "path": "./node_modules/cz-conventional-changelog" 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /poi.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | configureWebpack: { 3 | module: { 4 | rules: [ 5 | { 6 | resourceQuery: /blockType=readme/, 7 | loader: require.resolve('./example/vue-readme-loader') 8 | } 9 | ] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/converter.js: -------------------------------------------------------------------------------- 1 | import toNow from 'date-fns/distance_in_words_to_now' 2 | 3 | export default (date, locale, converterOptions) => { 4 | const { includeSeconds, addSuffix = true } = converterOptions 5 | return toNow(date, { 6 | locale, 7 | includeSeconds, 8 | addSuffix 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import defaultConverter from './converter' 2 | 3 | export const createTimeago = (opts = {}) => { 4 | const locales = opts.locales || {} 5 | const name = opts.name || 'Timeago' 6 | 7 | return { 8 | name, 9 | 10 | props: { 11 | datetime: { 12 | required: true 13 | }, 14 | title: { 15 | type: [String, Boolean] 16 | }, 17 | locale: { 18 | type: String 19 | }, 20 | autoUpdate: { 21 | type: [Number, Boolean] 22 | }, 23 | converter: { 24 | type: Function 25 | }, 26 | converterOptions: { 27 | type: Object 28 | } 29 | }, 30 | 31 | data() { 32 | return { 33 | timeago: this.getTimeago() 34 | } 35 | }, 36 | 37 | computed: { 38 | localeName() { 39 | return this.locale || this.$timeago.locale 40 | } 41 | }, 42 | 43 | mounted() { 44 | this.startUpdater() 45 | }, 46 | 47 | beforeDestroy() { 48 | this.stopUpdater() 49 | }, 50 | 51 | render(h) { 52 | return h( 53 | 'time', 54 | { 55 | attrs: { 56 | datetime: new Date(this.datetime).toISOString(), 57 | title: 58 | typeof this.title === 'string' 59 | ? this.title 60 | : this.title === false 61 | ? null 62 | : this.timeago 63 | } 64 | }, 65 | [this.timeago] 66 | ) 67 | }, 68 | 69 | methods: { 70 | getTimeago(datetime) { 71 | const converter = this.converter || opts.converter || defaultConverter 72 | return converter( 73 | datetime || this.datetime, 74 | locales[this.locale || this.$timeago.locale], 75 | this.converterOptions || {} 76 | ) 77 | }, 78 | 79 | convert(datetime) { 80 | this.timeago = this.getTimeago(datetime) 81 | }, 82 | 83 | startUpdater() { 84 | if (this.autoUpdate) { 85 | const autoUpdaye = this.autoUpdate === true ? 60 : this.autoUpdate 86 | this.updater = setInterval(() => { 87 | this.convert() 88 | }, autoUpdaye * 1000) 89 | } 90 | }, 91 | 92 | stopUpdater() { 93 | if (this.updater) { 94 | clearInterval(this.updater) 95 | this.updater = null 96 | } 97 | } 98 | }, 99 | 100 | watch: { 101 | autoUpdate(newValue) { 102 | this.stopUpdater() 103 | if (newValue) { 104 | this.startUpdater() 105 | } 106 | }, 107 | 108 | datetime() { 109 | this.convert() 110 | }, 111 | localeName() { 112 | this.convert() 113 | }, 114 | converter() { 115 | this.convert() 116 | }, 117 | converterOptions: { 118 | handler() { 119 | this.convert() 120 | }, 121 | deep: true 122 | } 123 | } 124 | } 125 | } 126 | 127 | export const install = (Vue, opts) => { 128 | if (Vue.prototype.$timeago) { 129 | return 130 | } 131 | 132 | if (process.env.NODE_ENV === 'development' && !Vue.observable) { 133 | console.warn(`[vue-timeago] Vue 2.6 or above is recommended.`) 134 | } 135 | 136 | const $timeago = { 137 | locale: opts.locale 138 | } 139 | Vue.prototype.$timeago = Vue.observable 140 | ? Vue.observable($timeago) 141 | : new Vue({ data: $timeago }) 142 | 143 | const Component = createTimeago(opts) 144 | Vue.component(Component.name, Component) 145 | } 146 | 147 | export const converter = defaultConverter 148 | 149 | export default install 150 | --------------------------------------------------------------------------------