├── .editorconfig
├── .eslintrc.js
├── .gitignore
├── .npmignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── src
├── index.js
└── index.spec.js
└── test
└── setup.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 4
9 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: "semistandard",
3 | rules: {
4 | semi: "error",
5 | quotes: ["error", "double"],
6 | "no-unused-expressions": "off",
7 | "comma-dangle": ["error", "always-multiline"],
8 | "prefer-const": "off",
9 | "no-var": "off",
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .editorconfig
2 | .eslintrc.js
3 | test
4 | src/**/*.spec.js
5 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [2.0.0] - 2020-05-30
4 |
5 | ### Breaking changes
6 |
7 | - Upgraded `date-fns` to version 2. All breaking changes from `date-fns` applies. Before upgrading to `date-fns@2` and `vue-date-fns@2`, please check `date-fns` docs for [format function](https://date-fns.org/v2.14.0/docs/format#v2.0.0-breaking-changes), their [blog explaining changes in the format](https://blog.date-fns.org/post/unicode-tokens-in-date-fns-v2-sreatyki91jg/) and their changelog for [common breaking changes](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes) in the `date-fns` library. It is very likely that your existing code will break.
8 |
9 | ### Other changes
10 |
11 | - Added default date format because it was removed from `date-fns` in version 2. It is now set to `"yyyy-MM-dd'T'HH:mm:ss.SSSxxx"`, same it was in version 1 of `date-fns`.
12 | - Resolved all security warnings
13 | - Bumped up all dev dependencies
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 M Cibique
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Date filter for Vue 2.X based on [date-fns](https://date-fns.org/)
2 |
3 | [](https://www.npmjs.com/package/vue-date-fns)
4 | [](https://bundlephobia.com/result?p=vue-date-fns)
5 |
6 | The `format` function from [date-fns](https://date-fns.org/) available as a filter for Vue apps. Why date-fns and not moment.js? There are already few [articles](https://medium.com/@k2u4yt/momentjs-vs-date-fns-6bddc7bfa21e), [covering](https://hackernoon.com/why-you-should-choose-date-fns-over-moment-js-in-your-nodejs-applications-116d1a709c43), [that](https://github.com/you-dont-need/You-Dont-Need-Momentjs).
7 |
8 | ## Disclaimer
9 |
10 | This package is just a Vue 2.X wrapper around `date-fns`. All important (and excellent) stuff is happening inside the `date-fns` library. If you found a bug please report it in their [issue tracker](https://github.com/date-fns/date-fns/issues) or help them and [contribute the PR](https://github.com/date-fns/date-fns/blob/master/CONTRIBUTING.md). If you like their package, [support them](https://opencollective.com/date-fns), because they're doing an amazing job.
11 |
12 | ## Installation
13 |
14 | ```sh
15 | npm install vue-date-fns --save
16 | ```
17 |
18 | or
19 |
20 | ```sh
21 | yarn add vue-date-fns
22 | ```
23 |
24 | `vue-date-fns` depends on `date-fns` version 2. If you are using the version 1 of `date-fns`, then install `vue-date-fns@1`, which is compatible.
25 |
26 | ### Breaking changes in version 2
27 |
28 | `vue-date-fns@2` inherits all **breaking changes** from `date-fns@2`, because it's just a wrapper around their `format` function. There were major breaking changes in the format API, e.g. `DD MMMM YYYY` should be from now on `dd MMMM yyyy`.
29 |
30 | Before upgrading to `date-fns@2` and `vue-date-fns@2`, please check `date-fns` docs for [format function](https://date-fns.org/v2.14.0/docs/format#v2.0.0-breaking-changes), their [blog explaining changes in the format](https://blog.date-fns.org/post/unicode-tokens-in-date-fns-v2-sreatyki91jg/) and their changelog for [common breaking changes](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes) in the `date-fns` library. It is very likely that your existing code will break.
31 |
32 | ## Usage
33 |
34 | ### Filter in individual component
35 |
36 | You can use filter directly in your component.
37 |
38 | ```js
39 | // my-component.js
40 | import { dateFilter } from "vue-date-fns";
41 |
42 | export default {
43 | filters: {
44 | date: dateFilter
45 | }
46 | }
47 | ```
48 |
49 | ```html
50 |
51 |
52 |
{{ myDate | date }}
", 18 | filters: { 19 | date: dateFilter, 20 | }, 21 | data () { 22 | return { 23 | myDate: date, 24 | }; 25 | }, 26 | }); 27 | 28 | let wrapper = mount(Wrapper); 29 | let text = wrapper.find("p").text(); 30 | expect(text).to.be.ok; 31 | expect(text).to.equal(formatDate(date, DEFAULT_DATE_FORMAT)); 32 | }); 33 | }); 34 | 35 | describe("with custom format", function () { 36 | it("should use the filter and produce the same output as date-fns", function () { 37 | let date = new Date(); 38 | let customFormat = "dd MMMM yyyy"; 39 | 40 | let Wrapper = Vue.extend({ 41 | template: `{{ myDate | date('${customFormat}') }}
`, 42 | filters: { 43 | date: dateFilter, 44 | }, 45 | data () { 46 | return { 47 | myDate: date, 48 | }; 49 | }, 50 | }); 51 | 52 | let wrapper = mount(Wrapper); 53 | let text = wrapper.find("p").text(); 54 | expect(text).to.be.ok; 55 | expect(text).to.equal(formatDate(date, customFormat)); 56 | }); 57 | }); 58 | 59 | describe("with custom format and options", function () { 60 | it("should use the filter and produce the same output as date-fns", function () { 61 | let date = new Date(); 62 | let customFormat = "dd MMMM yyyy"; 63 | let locale = require("date-fns/locale/sk"); 64 | 65 | let Wrapper = Vue.extend({ 66 | template: `{{ myDate | date('${customFormat}', { locale }) }}
`, 67 | filters: { 68 | date: dateFilter, 69 | }, 70 | data () { 71 | return { 72 | myDate: date, 73 | locale: locale, 74 | }; 75 | }, 76 | }); 77 | 78 | let wrapper = mount(Wrapper); 79 | let text = wrapper.find("p").text(); 80 | expect(text).to.be.ok; 81 | expect(text).to.equal(formatDate(date, customFormat, { locale })); 82 | }); 83 | }); 84 | 85 | describe("creating own filter with custom format", function () { 86 | it("should use the filter and produce the same output as date-fns", function () { 87 | let date = new Date(); 88 | let customFormat = "dd MMMM yyyy"; 89 | 90 | let Wrapper = Vue.extend({ 91 | template: "{{ myDate | date }}
", 92 | filters: { 93 | date: createDateFilter(customFormat), 94 | }, 95 | data () { 96 | return { 97 | myDate: date, 98 | }; 99 | }, 100 | }); 101 | 102 | let wrapper = mount(Wrapper); 103 | let text = wrapper.find("p").text(); 104 | expect(text).to.be.ok; 105 | expect(text).to.equal(formatDate(date, customFormat)); 106 | }); 107 | }); 108 | 109 | describe("creating own filter with custom format and custom defaults", function () { 110 | it("should use the filter and produce the same output as date-fns", function () { 111 | let date = new Date(); 112 | let customFormat = "dd MMMM yyyy"; 113 | let locale = require("date-fns/locale/sk"); 114 | 115 | let Wrapper = Vue.extend({ 116 | template: "{{ myDate | date }}
", 117 | filters: { 118 | date: createDateFilter(customFormat, { locale }), 119 | }, 120 | data () { 121 | return { 122 | myDate: date, 123 | }; 124 | }, 125 | }); 126 | 127 | let wrapper = mount(Wrapper); 128 | let text = wrapper.find("p").text(); 129 | expect(text).to.be.ok; 130 | expect(text).to.equal(formatDate(date, customFormat, { locale })); 131 | }); 132 | }); 133 | }); 134 | 135 | describe("using global filter", function () { 136 | let localVue; 137 | 138 | beforeEach(function () { 139 | localVue = createLocalVue(); 140 | localVue.use(DateFnsPlugin); 141 | }); 142 | 143 | it("should have registered filter with default name globally", function () { 144 | expect(localVue.filter("date")).to.be.a("function"); 145 | }); 146 | 147 | describe("without any options", function () { 148 | it("should use the filter and produce the same output as date-fns", function () { 149 | let date = new Date(); 150 | 151 | let Wrapper = localVue.extend({ 152 | template: "{{ myDate | date }}
", 153 | data () { 154 | return { 155 | myDate: date, 156 | }; 157 | }, 158 | }); 159 | 160 | let wrapper = mount(Wrapper, { localVue }); 161 | let text = wrapper.find("p").text(); 162 | expect(text).to.be.ok; 163 | expect(text).to.equal(formatDate(date, DEFAULT_DATE_FORMAT)); 164 | }); 165 | }); 166 | 167 | describe("with custom format", function () { 168 | it("should use the filter and produce the same output as date-fns", function () { 169 | let date = new Date(); 170 | let customFormat = "dd MMMM yyyy"; 171 | 172 | let Wrapper = localVue.extend({ 173 | template: `{{ myDate | date('${customFormat}') }}
`, 174 | data () { 175 | return { 176 | myDate: date, 177 | }; 178 | }, 179 | }); 180 | 181 | let wrapper = mount(Wrapper, { localVue }); 182 | let text = wrapper.find("p").text(); 183 | expect(text).to.be.ok; 184 | expect(text).to.equal(formatDate(date, customFormat)); 185 | }); 186 | }); 187 | 188 | describe("with custom format and options", function () { 189 | it("should use the filter and produce the same output as date-fns", function () { 190 | let date = new Date(); 191 | let customFormat = "dd MMMM yyyy"; 192 | let locale = require("date-fns/locale/sk"); 193 | 194 | let Wrapper = localVue.extend({ 195 | template: `{{ myDate | date('${customFormat}', { locale }) }}
`, 196 | data () { 197 | return { 198 | myDate: date, 199 | locale: locale, 200 | }; 201 | }, 202 | }); 203 | 204 | let wrapper = mount(Wrapper, { localVue }); 205 | let text = wrapper.find("p").text(); 206 | expect(text).to.be.ok; 207 | expect(text).to.equal(formatDate(date, customFormat, { locale })); 208 | }); 209 | }); 210 | }); 211 | 212 | describe("using global filter with custom format", function () { 213 | let localVue; 214 | let customFormat = "dd MMMM yyyy"; 215 | 216 | beforeEach(function () { 217 | localVue = createLocalVue(); 218 | localVue.use(DateFnsPlugin, customFormat); 219 | }); 220 | 221 | it("should have registered filter with default name globally", function () { 222 | expect(localVue.filter("date")).to.be.a("function"); 223 | }); 224 | 225 | describe("without any options", function () { 226 | it("should use the filter and produce the same output as date-fns", function () { 227 | let date = new Date(); 228 | 229 | let Wrapper = localVue.extend({ 230 | template: "{{ myDate | date }}
", 231 | data () { 232 | return { 233 | myDate: date, 234 | }; 235 | }, 236 | }); 237 | 238 | let wrapper = mount(Wrapper, { localVue }); 239 | let text = wrapper.find("p").text(); 240 | expect(text).to.be.ok; 241 | expect(text).to.equal(formatDate(date, customFormat)); 242 | }); 243 | }); 244 | 245 | describe("with custom format", function () { 246 | it("should use the filter and produce the same output as date-fns", function () { 247 | let date = new Date(); 248 | let differentCustomFormat = "dd MMMM yyyy HH:mm"; 249 | 250 | let Wrapper = localVue.extend({ 251 | template: `{{ myDate | date('${differentCustomFormat}') }}
`, 252 | data () { 253 | return { 254 | myDate: date, 255 | }; 256 | }, 257 | }); 258 | 259 | let wrapper = mount(Wrapper, { localVue }); 260 | let text = wrapper.find("p").text(); 261 | expect(text).to.be.ok; 262 | expect(text).to.equal(formatDate(date, differentCustomFormat)); 263 | }); 264 | }); 265 | 266 | describe("with custom format and options", function () { 267 | it("should use the filter and produce the same output as date-fns", function () { 268 | let date = new Date(); 269 | let differentCustomFormat = "dd MMMM yyyy HH:mm"; 270 | let locale = require("date-fns/locale/sk"); 271 | 272 | let Wrapper = localVue.extend({ 273 | template: `{{ myDate | date('${differentCustomFormat}', { locale }) }}
`, 274 | data () { 275 | return { 276 | myDate: date, 277 | locale: locale, 278 | }; 279 | }, 280 | }); 281 | 282 | let wrapper = mount(Wrapper, { localVue }); 283 | let text = wrapper.find("p").text(); 284 | expect(text).to.be.ok; 285 | expect(text).to.equal(formatDate(date, differentCustomFormat, { locale })); 286 | }); 287 | }); 288 | }); 289 | 290 | describe("using global filter with custom format and custom defaults", function () { 291 | let localVue; 292 | let customFormat = "dd MMMM yyyy"; 293 | let locale = require("date-fns/locale/ar-SA"); 294 | 295 | beforeEach(function () { 296 | localVue = createLocalVue(); 297 | localVue.use(DateFnsPlugin, customFormat, { locale }); 298 | }); 299 | 300 | it("should have registered filter with default name globally", function () { 301 | expect(localVue.filter("date")).to.be.a("function"); 302 | }); 303 | 304 | describe("without any options", function () { 305 | it("should use the filter and produce the same output as date-fns", function () { 306 | let date = new Date(); 307 | 308 | let Wrapper = localVue.extend({ 309 | template: "{{ myDate | date }}
", 310 | data () { 311 | return { 312 | myDate: date, 313 | }; 314 | }, 315 | }); 316 | 317 | let wrapper = mount(Wrapper, { localVue }); 318 | let text = wrapper.find("p").text(); 319 | expect(text).to.be.ok; 320 | expect(text).to.equal(formatDate(date, customFormat, { locale })); 321 | }); 322 | }); 323 | 324 | describe("with custom format", function () { 325 | it("should use the filter and produce the same output as date-fns", function () { 326 | let date = new Date(); 327 | let differentCustomFormat = "dd MMMM yyyy HH:mm"; 328 | 329 | let Wrapper = localVue.extend({ 330 | template: `{{ myDate | date('${differentCustomFormat}') }}
`, 331 | data () { 332 | return { 333 | myDate: date, 334 | }; 335 | }, 336 | }); 337 | 338 | let wrapper = mount(Wrapper, { localVue }); 339 | let text = wrapper.find("p").text(); 340 | expect(text).to.be.ok; 341 | expect(text).to.equal(formatDate(date, differentCustomFormat, { locale })); 342 | }); 343 | }); 344 | 345 | describe("with custom format and options", function () { 346 | it("should use the filter and produce the same output as date-fns", function () { 347 | let date = new Date(); 348 | let differentCustomFormat = "dd MMMM yyyy HH:mm"; 349 | let differentLocale = require("date-fns/locale/sk"); 350 | 351 | let Wrapper = localVue.extend({ 352 | template: `{{ myDate | date('${differentCustomFormat}', { locale }) }}
`, 353 | data () { 354 | return { 355 | myDate: date, 356 | locale: differentLocale, 357 | }; 358 | }, 359 | }); 360 | 361 | let wrapper = mount(Wrapper, { localVue }); 362 | let text = wrapper.find("p").text(); 363 | expect(text).to.be.ok; 364 | expect(text).to.equal(formatDate(date, differentCustomFormat, { locale: differentLocale })); 365 | }); 366 | }); 367 | }); 368 | 369 | describe("using global filter with custom filter name", function () { 370 | let localVue; 371 | 372 | beforeEach(function () { 373 | localVue = createLocalVue(); 374 | localVue.use(DateFnsPlugin, null, null, "myDateFilter"); 375 | }); 376 | 377 | it("should have registered filter with given name globally", function () { 378 | expect(localVue.filter("myDateFilter")).to.be.a("function"); 379 | }); 380 | 381 | it("should NOT have registered filter with default name globally", function () { 382 | expect(localVue.filter("date")).to.be.undefined; 383 | }); 384 | 385 | it("should use the filter and produce the same output as date-fns", function () { 386 | let date = new Date(); 387 | 388 | let Wrapper = localVue.extend({ 389 | template: "{{ myDate | myDateFilter }}
", 390 | data () { 391 | return { 392 | myDate: date, 393 | }; 394 | }, 395 | }); 396 | 397 | let wrapper = mount(Wrapper, { localVue }); 398 | let text = wrapper.find("p").text(); 399 | expect(text).to.be.ok; 400 | expect(text).to.equal(formatDate(date, DEFAULT_DATE_FORMAT)); 401 | }); 402 | }); 403 | 404 | describe("using mixin", function () { 405 | let localVue; 406 | 407 | beforeEach(function () { 408 | localVue = createLocalVue(); 409 | localVue.use(DateFnsPlugin); 410 | }); 411 | 412 | it("should have registered filter with default name globally", function () { 413 | // eslint-disable-next-line new-cap 414 | expect(new localVue().$date).to.be.a("function"); 415 | }); 416 | 417 | describe("without any options", function () { 418 | it("should use mixin and produce the same output as date-fns", function () { 419 | let date = new Date(); 420 | 421 | let Wrapper = localVue.extend({ 422 | template: "{{ $date(myDate) }}
", 423 | data () { 424 | return { 425 | myDate: date, 426 | }; 427 | }, 428 | }); 429 | 430 | let wrapper = mount(Wrapper, { localVue }); 431 | let text = wrapper.find("p").text(); 432 | expect(text).to.be.ok; 433 | expect(text).to.equal(formatDate(date, DEFAULT_DATE_FORMAT)); 434 | }); 435 | }); 436 | 437 | describe("with custom format", function () { 438 | it("should use mixin and produce the same output as date-fns", function () { 439 | let date = new Date(); 440 | let customFormat = "dd MMMM yyyy HH:mm"; 441 | 442 | let Wrapper = localVue.extend({ 443 | template: `{{ $date(myDate, '${customFormat}') }}
`, 444 | data () { 445 | return { 446 | myDate: date, 447 | }; 448 | }, 449 | }); 450 | 451 | let wrapper = mount(Wrapper, { localVue }); 452 | let text = wrapper.find("p").text(); 453 | expect(text).to.be.ok; 454 | expect(text).to.equal(formatDate(date, customFormat)); 455 | }); 456 | }); 457 | 458 | describe("with custom format and options", function () { 459 | it("should use the filter and produce the same output as date-fns", function () { 460 | let date = new Date(); 461 | let customFormat = "dd MMMM yyyy HH:mm"; 462 | let locale = require("date-fns/locale/sk"); 463 | 464 | let Wrapper = localVue.extend({ 465 | template: `{{ $date(myDate, '${customFormat}', { locale }) }}
`, 466 | data () { 467 | return { 468 | myDate: date, 469 | locale: locale, 470 | }; 471 | }, 472 | }); 473 | 474 | let wrapper = mount(Wrapper, { localVue }); 475 | let text = wrapper.find("p").text(); 476 | expect(text).to.be.ok; 477 | expect(text).to.equal(formatDate(date, customFormat, { locale })); 478 | }); 479 | }); 480 | }); 481 | 482 | describe("using mixing with custom filter name", function () { 483 | let localVue; 484 | 485 | beforeEach(function () { 486 | localVue = createLocalVue(); 487 | localVue.use(DateFnsPlugin, null, null, "myDateFilter"); 488 | }); 489 | 490 | it("should have registered filter with given name globally", function () { 491 | // eslint-disable-next-line new-cap 492 | expect(new localVue().$myDateFilter).to.be.a("function"); 493 | }); 494 | 495 | it("should NOT have registered filter with default name globally", function () { 496 | // eslint-disable-next-line new-cap 497 | expect(new localVue().$date).to.be.undefined; 498 | }); 499 | 500 | it("should use mixin and produce the same output as date-fns", function () { 501 | let date = new Date(); 502 | 503 | let Wrapper = localVue.extend({ 504 | template: "{{ $myDateFilter(myDate) }}
", 505 | data () { 506 | return { 507 | myDate: date, 508 | }; 509 | }, 510 | }); 511 | 512 | let wrapper = mount(Wrapper, { localVue }); 513 | let text = wrapper.find("p").text(); 514 | expect(text).to.be.ok; 515 | expect(text).to.equal(formatDate(date, DEFAULT_DATE_FORMAT)); 516 | }); 517 | }); 518 | 519 | describe("falsy values", function () { 520 | for (let testCase of [undefined, null, "", NaN]) { 521 | it(`should return empty string for '${testCase}'`, function () { 522 | expect(dateFilter(testCase)).to.equal(""); 523 | }); 524 | } 525 | }); 526 | -------------------------------------------------------------------------------- /test/setup.js: -------------------------------------------------------------------------------- 1 | require("jsdom-global")(); 2 | --------------------------------------------------------------------------------