svelte-copyright 1.1.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/index.js +142 -72
- package/lib/index.mjs +140 -71
- package/package.json +15 -14
- package/src/Copyright.svelte +7 -6
- package/src/__tests__/Copyright.spec.js +17 -19
- package/src/utils/__test__/date.spec.js +63 -22
- package/src/utils/date.js +43 -24
- package/src/utils/index.js +1 -1
package/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
<h1>svelte-copyright</h1>
|
|
3
3
|
<p style="font-style: italic;">© A Svelte component to format and display a copyright notice.</p>
|
|
4
4
|
<div>
|
|
5
|
-
<a href='https://
|
|
6
|
-
<img src="https://
|
|
5
|
+
<a href='https://github.com/himynameisdave/svelte-copyright/actions?query=workflow%3Atest+branch%3Amaster'>
|
|
6
|
+
<img src="https://github.com/himynameisdave/svelte-copyright/workflows/test/badge.svg" alt="GitHub Actions - Test Workflow Badge" />
|
|
7
7
|
</a>
|
|
8
8
|
<a href="https://packagephobia.now.sh/result?p=svelte-copyright">
|
|
9
9
|
<img src="https://packagephobia.now.sh/badge?p=svelte-copyright" alt="Install size" />
|
package/lib/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
3
|
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Copyright = {}));
|
|
5
|
-
}(this, (function (exports) { 'use strict';
|
|
5
|
+
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function noop() { }
|
|
8
8
|
function assign(tar, src) {
|
|
@@ -58,13 +58,23 @@
|
|
|
58
58
|
}
|
|
59
59
|
return $$scope.dirty;
|
|
60
60
|
}
|
|
61
|
-
function
|
|
62
|
-
const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
|
|
61
|
+
function update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn) {
|
|
63
62
|
if (slot_changes) {
|
|
64
63
|
const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
|
|
65
64
|
slot.p(slot_context, slot_changes);
|
|
66
65
|
}
|
|
67
66
|
}
|
|
67
|
+
function get_all_dirty_from_scope($$scope) {
|
|
68
|
+
if ($$scope.ctx.length > 32) {
|
|
69
|
+
const dirty = [];
|
|
70
|
+
const length = $$scope.ctx.length / 32;
|
|
71
|
+
for (let i = 0; i < length; i++) {
|
|
72
|
+
dirty[i] = -1;
|
|
73
|
+
}
|
|
74
|
+
return dirty;
|
|
75
|
+
}
|
|
76
|
+
return -1;
|
|
77
|
+
}
|
|
68
78
|
function exclude_internal_props(props) {
|
|
69
79
|
const result = {};
|
|
70
80
|
for (const k in props)
|
|
@@ -80,7 +90,6 @@
|
|
|
80
90
|
rest[k] = props[k];
|
|
81
91
|
return rest;
|
|
82
92
|
}
|
|
83
|
-
|
|
84
93
|
function append(target, node) {
|
|
85
94
|
target.appendChild(node);
|
|
86
95
|
}
|
|
@@ -88,7 +97,9 @@
|
|
|
88
97
|
target.insertBefore(node, anchor || null);
|
|
89
98
|
}
|
|
90
99
|
function detach(node) {
|
|
91
|
-
node.parentNode
|
|
100
|
+
if (node.parentNode) {
|
|
101
|
+
node.parentNode.removeChild(node);
|
|
102
|
+
}
|
|
92
103
|
}
|
|
93
104
|
function element(name) {
|
|
94
105
|
return document.createElement(name);
|
|
@@ -150,22 +161,40 @@
|
|
|
150
161
|
function add_render_callback(fn) {
|
|
151
162
|
render_callbacks.push(fn);
|
|
152
163
|
}
|
|
153
|
-
|
|
164
|
+
// flush() calls callbacks in this order:
|
|
165
|
+
// 1. All beforeUpdate callbacks, in order: parents before children
|
|
166
|
+
// 2. All bind:this callbacks, in reverse order: children before parents.
|
|
167
|
+
// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
|
|
168
|
+
// for afterUpdates called during the initial onMount, which are called in
|
|
169
|
+
// reverse order: children before parents.
|
|
170
|
+
// Since callbacks might update component values, which could trigger another
|
|
171
|
+
// call to flush(), the following steps guard against this:
|
|
172
|
+
// 1. During beforeUpdate, any updated components will be added to the
|
|
173
|
+
// dirty_components array and will cause a reentrant call to flush(). Because
|
|
174
|
+
// the flush index is kept outside the function, the reentrant call will pick
|
|
175
|
+
// up where the earlier call left off and go through all dirty components. The
|
|
176
|
+
// current_component value is saved and restored so that the reentrant call will
|
|
177
|
+
// not interfere with the "parent" flush() call.
|
|
178
|
+
// 2. bind:this callbacks cannot trigger new flush() calls.
|
|
179
|
+
// 3. During afterUpdate, any updated components will NOT have their afterUpdate
|
|
180
|
+
// callback called a second time; the seen_callbacks set, outside the flush()
|
|
181
|
+
// function, guarantees this behavior.
|
|
154
182
|
const seen_callbacks = new Set();
|
|
183
|
+
let flushidx = 0; // Do *not* move this inside the flush() function
|
|
155
184
|
function flush() {
|
|
156
|
-
|
|
157
|
-
return;
|
|
158
|
-
flushing = true;
|
|
185
|
+
const saved_component = current_component;
|
|
159
186
|
do {
|
|
160
187
|
// first, call beforeUpdate functions
|
|
161
188
|
// and update components
|
|
162
|
-
|
|
163
|
-
const component = dirty_components[
|
|
189
|
+
while (flushidx < dirty_components.length) {
|
|
190
|
+
const component = dirty_components[flushidx];
|
|
191
|
+
flushidx++;
|
|
164
192
|
set_current_component(component);
|
|
165
193
|
update(component.$$);
|
|
166
194
|
}
|
|
167
195
|
set_current_component(null);
|
|
168
196
|
dirty_components.length = 0;
|
|
197
|
+
flushidx = 0;
|
|
169
198
|
while (binding_callbacks.length)
|
|
170
199
|
binding_callbacks.pop()();
|
|
171
200
|
// then, once components are updated, call
|
|
@@ -185,8 +214,8 @@
|
|
|
185
214
|
flush_callbacks.pop()();
|
|
186
215
|
}
|
|
187
216
|
update_scheduled = false;
|
|
188
|
-
flushing = false;
|
|
189
217
|
seen_callbacks.clear();
|
|
218
|
+
set_current_component(saved_component);
|
|
190
219
|
}
|
|
191
220
|
function update($$) {
|
|
192
221
|
if ($$.fragment !== null) {
|
|
@@ -221,6 +250,9 @@
|
|
|
221
250
|
});
|
|
222
251
|
block.o(local);
|
|
223
252
|
}
|
|
253
|
+
else if (callback) {
|
|
254
|
+
callback();
|
|
255
|
+
}
|
|
224
256
|
}
|
|
225
257
|
|
|
226
258
|
function get_spread_update(levels, updates) {
|
|
@@ -256,22 +288,27 @@
|
|
|
256
288
|
}
|
|
257
289
|
return update;
|
|
258
290
|
}
|
|
259
|
-
function mount_component(component, target, anchor) {
|
|
260
|
-
const { fragment,
|
|
291
|
+
function mount_component(component, target, anchor, customElement) {
|
|
292
|
+
const { fragment, after_update } = component.$$;
|
|
261
293
|
fragment && fragment.m(target, anchor);
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
294
|
+
if (!customElement) {
|
|
295
|
+
// onMount happens before the initial afterUpdate
|
|
296
|
+
add_render_callback(() => {
|
|
297
|
+
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
|
|
298
|
+
// if the component was destroyed immediately
|
|
299
|
+
// it will update the `$$.on_destroy` reference to `null`.
|
|
300
|
+
// the destructured on_destroy may still reference to the old array
|
|
301
|
+
if (component.$$.on_destroy) {
|
|
302
|
+
component.$$.on_destroy.push(...new_on_destroy);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
// Edge case - component was destroyed immediately,
|
|
306
|
+
// most likely as a result of a binding initialising
|
|
307
|
+
run_all(new_on_destroy);
|
|
308
|
+
}
|
|
309
|
+
component.$$.on_mount = [];
|
|
310
|
+
});
|
|
311
|
+
}
|
|
275
312
|
after_update.forEach(add_render_callback);
|
|
276
313
|
}
|
|
277
314
|
function destroy_component(component, detaching) {
|
|
@@ -293,12 +330,12 @@
|
|
|
293
330
|
}
|
|
294
331
|
component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
|
|
295
332
|
}
|
|
296
|
-
function init(component, options, instance, create_fragment, not_equal, props, dirty = [-1]) {
|
|
333
|
+
function init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {
|
|
297
334
|
const parent_component = current_component;
|
|
298
335
|
set_current_component(component);
|
|
299
336
|
const $$ = component.$$ = {
|
|
300
337
|
fragment: null,
|
|
301
|
-
ctx:
|
|
338
|
+
ctx: [],
|
|
302
339
|
// state
|
|
303
340
|
props,
|
|
304
341
|
update: noop,
|
|
@@ -307,14 +344,17 @@
|
|
|
307
344
|
// lifecycle
|
|
308
345
|
on_mount: [],
|
|
309
346
|
on_destroy: [],
|
|
347
|
+
on_disconnect: [],
|
|
310
348
|
before_update: [],
|
|
311
349
|
after_update: [],
|
|
312
|
-
context: new Map(parent_component ? parent_component.$$.context : []),
|
|
350
|
+
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
|
|
313
351
|
// everything else
|
|
314
352
|
callbacks: blank_object(),
|
|
315
353
|
dirty,
|
|
316
|
-
skip_bound: false
|
|
354
|
+
skip_bound: false,
|
|
355
|
+
root: options.target || parent_component.$$.root
|
|
317
356
|
};
|
|
357
|
+
append_styles && append_styles($$.root);
|
|
318
358
|
let ready = false;
|
|
319
359
|
$$.ctx = instance
|
|
320
360
|
? instance(component, options.props || {}, (i, ret, ...rest) => {
|
|
@@ -346,7 +386,7 @@
|
|
|
346
386
|
}
|
|
347
387
|
if (options.intro)
|
|
348
388
|
transition_in(component.$$.fragment);
|
|
349
|
-
mount_component(component, options.target, options.anchor);
|
|
389
|
+
mount_component(component, options.target, options.anchor, options.customElement);
|
|
350
390
|
flush();
|
|
351
391
|
}
|
|
352
392
|
set_current_component(parent_component);
|
|
@@ -360,6 +400,9 @@
|
|
|
360
400
|
this.$destroy = noop;
|
|
361
401
|
}
|
|
362
402
|
$on(type, callback) {
|
|
403
|
+
if (!is_function(callback)) {
|
|
404
|
+
return noop;
|
|
405
|
+
}
|
|
363
406
|
const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
|
|
364
407
|
callbacks.push(callback);
|
|
365
408
|
return () => {
|
|
@@ -403,39 +446,58 @@
|
|
|
403
446
|
return date.getFullYear().toString();
|
|
404
447
|
}
|
|
405
448
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
449
|
+
/**
|
|
450
|
+
* Formats the date, just for you!
|
|
451
|
+
*
|
|
452
|
+
* @param {Date} date - Date to format
|
|
453
|
+
* @param {'numeric' | '2-digit'} format - Format for the date.
|
|
454
|
+
*/
|
|
455
|
+
function formatDate(date = today(), format = FORMAT.NUMERIC) {
|
|
456
|
+
if (format === FORMAT.NUMERIC) {
|
|
457
|
+
return toYear(date);
|
|
458
|
+
}
|
|
459
|
+
if (format === FORMAT.TWO_DIGIT) {
|
|
460
|
+
return `’${toYear(date).slice(-2)}`;
|
|
415
461
|
}
|
|
416
462
|
}
|
|
417
463
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
464
|
+
/**
|
|
465
|
+
* Returns the "range string", unless the dates are the same.
|
|
466
|
+
*
|
|
467
|
+
* @param {string} date1 - First date (formatted to a string)
|
|
468
|
+
* @param {string} date2 - Second date (formatted to a string).
|
|
469
|
+
*/
|
|
470
|
+
function getRange(date1, date2) {
|
|
471
|
+
// Don't show a range if years are the same, as that would be dumb.
|
|
472
|
+
if (date1 === date2) {
|
|
473
|
+
return date1;
|
|
474
|
+
}
|
|
475
|
+
return `${date1} - ${date2}`;
|
|
421
476
|
}
|
|
422
477
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
478
|
+
/**
|
|
479
|
+
* Returns the displayed date for the component.
|
|
480
|
+
*
|
|
481
|
+
* @param {boolean} options.showRange - If a date range should be displayed.
|
|
482
|
+
* @param {Date} options.date - Copyright year to be used. If showRange is true, this is the start year of the range.
|
|
483
|
+
* @param {'numeric' | '2-digit'} options.format - Date format to be used.
|
|
484
|
+
*/
|
|
485
|
+
function getDisplayDate({
|
|
486
|
+
showRange = false,
|
|
487
|
+
date = today(),
|
|
488
|
+
format = FORMAT.NUMERIC,
|
|
489
|
+
}) {
|
|
490
|
+
const formatted = formatDate(date, format);
|
|
491
|
+
// Early return if we don't show the range
|
|
492
|
+
if (!showRange) {
|
|
493
|
+
return formatted;
|
|
435
494
|
}
|
|
495
|
+
// Get today's year, formatted correctly.
|
|
496
|
+
const formattedToday = formatDate(today(), format);
|
|
497
|
+
return getRange(formatted, formattedToday);
|
|
436
498
|
}
|
|
437
499
|
|
|
438
|
-
/* src/Copyright.svelte generated by Svelte v3.
|
|
500
|
+
/* src/Copyright.svelte generated by Svelte v3.54.0 */
|
|
439
501
|
|
|
440
502
|
function create_if_block_1(ctx) {
|
|
441
503
|
let t0;
|
|
@@ -458,7 +520,7 @@
|
|
|
458
520
|
};
|
|
459
521
|
}
|
|
460
522
|
|
|
461
|
-
// (
|
|
523
|
+
// (27:2) {#if position === POSITION.POST}
|
|
462
524
|
function create_if_block(ctx) {
|
|
463
525
|
let t0;
|
|
464
526
|
let t1;
|
|
@@ -534,8 +596,17 @@
|
|
|
534
596
|
}
|
|
535
597
|
|
|
536
598
|
if (default_slot) {
|
|
537
|
-
if (default_slot.p && dirty & /*$$scope*/ 64) {
|
|
538
|
-
|
|
599
|
+
if (default_slot.p && (!current || dirty & /*$$scope*/ 64)) {
|
|
600
|
+
update_slot_base(
|
|
601
|
+
default_slot,
|
|
602
|
+
default_slot_template,
|
|
603
|
+
ctx,
|
|
604
|
+
/*$$scope*/ ctx[6],
|
|
605
|
+
!current
|
|
606
|
+
? get_all_dirty_from_scope(/*$$scope*/ ctx[6])
|
|
607
|
+
: get_slot_changes(default_slot_template, /*$$scope*/ ctx[6], dirty, null),
|
|
608
|
+
null
|
|
609
|
+
);
|
|
539
610
|
}
|
|
540
611
|
}
|
|
541
612
|
|
|
@@ -576,25 +647,22 @@
|
|
|
576
647
|
const omit_props_names = ["date","format","position","showRange"];
|
|
577
648
|
let $$restProps = compute_rest_props($$props, omit_props_names);
|
|
578
649
|
let { $$slots: slots = {}, $$scope } = $$props;
|
|
579
|
-
let { date =
|
|
650
|
+
let { date = today() } = $$props;
|
|
580
651
|
let { format = FORMAT.NUMERIC } = $$props;
|
|
581
652
|
let { position = POSITION.PRE } = $$props;
|
|
582
653
|
let { showRange = false } = $$props;
|
|
583
654
|
|
|
584
655
|
// Get the formatDate function
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
const getDateRange = withGetDateRange(showRange);
|
|
588
|
-
let displayDate = getDateRange(date, formatDate);
|
|
656
|
+
let displayDate = getDisplayDate({ showRange, format, date });
|
|
589
657
|
|
|
590
658
|
$$self.$$set = $$new_props => {
|
|
591
659
|
$$props = assign(assign({}, $$props), exclude_internal_props($$new_props));
|
|
592
660
|
$$invalidate(2, $$restProps = compute_rest_props($$props, omit_props_names));
|
|
593
|
-
if (
|
|
594
|
-
if (
|
|
595
|
-
if (
|
|
596
|
-
if (
|
|
597
|
-
if (
|
|
661
|
+
if ('date' in $$new_props) $$invalidate(3, date = $$new_props.date);
|
|
662
|
+
if ('format' in $$new_props) $$invalidate(4, format = $$new_props.format);
|
|
663
|
+
if ('position' in $$new_props) $$invalidate(0, position = $$new_props.position);
|
|
664
|
+
if ('showRange' in $$new_props) $$invalidate(5, showRange = $$new_props.showRange);
|
|
665
|
+
if ('$$scope' in $$new_props) $$invalidate(6, $$scope = $$new_props.$$scope);
|
|
598
666
|
};
|
|
599
667
|
|
|
600
668
|
return [position, displayDate, $$restProps, date, format, showRange, $$scope, slots];
|
|
@@ -613,9 +681,11 @@
|
|
|
613
681
|
}
|
|
614
682
|
}
|
|
615
683
|
|
|
684
|
+
var Copyright$1 = Copyright;
|
|
685
|
+
|
|
616
686
|
exports.constants = constants;
|
|
617
|
-
exports.default = Copyright;
|
|
687
|
+
exports.default = Copyright$1;
|
|
618
688
|
|
|
619
689
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
620
690
|
|
|
621
|
-
}))
|
|
691
|
+
}));
|
package/lib/index.mjs
CHANGED
|
@@ -52,13 +52,23 @@ function get_slot_changes(definition, $$scope, dirty, fn) {
|
|
|
52
52
|
}
|
|
53
53
|
return $$scope.dirty;
|
|
54
54
|
}
|
|
55
|
-
function
|
|
56
|
-
const slot_changes = get_slot_changes(slot_definition, $$scope, dirty, get_slot_changes_fn);
|
|
55
|
+
function update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn) {
|
|
57
56
|
if (slot_changes) {
|
|
58
57
|
const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
|
|
59
58
|
slot.p(slot_context, slot_changes);
|
|
60
59
|
}
|
|
61
60
|
}
|
|
61
|
+
function get_all_dirty_from_scope($$scope) {
|
|
62
|
+
if ($$scope.ctx.length > 32) {
|
|
63
|
+
const dirty = [];
|
|
64
|
+
const length = $$scope.ctx.length / 32;
|
|
65
|
+
for (let i = 0; i < length; i++) {
|
|
66
|
+
dirty[i] = -1;
|
|
67
|
+
}
|
|
68
|
+
return dirty;
|
|
69
|
+
}
|
|
70
|
+
return -1;
|
|
71
|
+
}
|
|
62
72
|
function exclude_internal_props(props) {
|
|
63
73
|
const result = {};
|
|
64
74
|
for (const k in props)
|
|
@@ -74,7 +84,6 @@ function compute_rest_props(props, keys) {
|
|
|
74
84
|
rest[k] = props[k];
|
|
75
85
|
return rest;
|
|
76
86
|
}
|
|
77
|
-
|
|
78
87
|
function append(target, node) {
|
|
79
88
|
target.appendChild(node);
|
|
80
89
|
}
|
|
@@ -82,7 +91,9 @@ function insert(target, node, anchor) {
|
|
|
82
91
|
target.insertBefore(node, anchor || null);
|
|
83
92
|
}
|
|
84
93
|
function detach(node) {
|
|
85
|
-
node.parentNode
|
|
94
|
+
if (node.parentNode) {
|
|
95
|
+
node.parentNode.removeChild(node);
|
|
96
|
+
}
|
|
86
97
|
}
|
|
87
98
|
function element(name) {
|
|
88
99
|
return document.createElement(name);
|
|
@@ -144,22 +155,40 @@ function schedule_update() {
|
|
|
144
155
|
function add_render_callback(fn) {
|
|
145
156
|
render_callbacks.push(fn);
|
|
146
157
|
}
|
|
147
|
-
|
|
158
|
+
// flush() calls callbacks in this order:
|
|
159
|
+
// 1. All beforeUpdate callbacks, in order: parents before children
|
|
160
|
+
// 2. All bind:this callbacks, in reverse order: children before parents.
|
|
161
|
+
// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
|
|
162
|
+
// for afterUpdates called during the initial onMount, which are called in
|
|
163
|
+
// reverse order: children before parents.
|
|
164
|
+
// Since callbacks might update component values, which could trigger another
|
|
165
|
+
// call to flush(), the following steps guard against this:
|
|
166
|
+
// 1. During beforeUpdate, any updated components will be added to the
|
|
167
|
+
// dirty_components array and will cause a reentrant call to flush(). Because
|
|
168
|
+
// the flush index is kept outside the function, the reentrant call will pick
|
|
169
|
+
// up where the earlier call left off and go through all dirty components. The
|
|
170
|
+
// current_component value is saved and restored so that the reentrant call will
|
|
171
|
+
// not interfere with the "parent" flush() call.
|
|
172
|
+
// 2. bind:this callbacks cannot trigger new flush() calls.
|
|
173
|
+
// 3. During afterUpdate, any updated components will NOT have their afterUpdate
|
|
174
|
+
// callback called a second time; the seen_callbacks set, outside the flush()
|
|
175
|
+
// function, guarantees this behavior.
|
|
148
176
|
const seen_callbacks = new Set();
|
|
177
|
+
let flushidx = 0; // Do *not* move this inside the flush() function
|
|
149
178
|
function flush() {
|
|
150
|
-
|
|
151
|
-
return;
|
|
152
|
-
flushing = true;
|
|
179
|
+
const saved_component = current_component;
|
|
153
180
|
do {
|
|
154
181
|
// first, call beforeUpdate functions
|
|
155
182
|
// and update components
|
|
156
|
-
|
|
157
|
-
const component = dirty_components[
|
|
183
|
+
while (flushidx < dirty_components.length) {
|
|
184
|
+
const component = dirty_components[flushidx];
|
|
185
|
+
flushidx++;
|
|
158
186
|
set_current_component(component);
|
|
159
187
|
update(component.$$);
|
|
160
188
|
}
|
|
161
189
|
set_current_component(null);
|
|
162
190
|
dirty_components.length = 0;
|
|
191
|
+
flushidx = 0;
|
|
163
192
|
while (binding_callbacks.length)
|
|
164
193
|
binding_callbacks.pop()();
|
|
165
194
|
// then, once components are updated, call
|
|
@@ -179,8 +208,8 @@ function flush() {
|
|
|
179
208
|
flush_callbacks.pop()();
|
|
180
209
|
}
|
|
181
210
|
update_scheduled = false;
|
|
182
|
-
flushing = false;
|
|
183
211
|
seen_callbacks.clear();
|
|
212
|
+
set_current_component(saved_component);
|
|
184
213
|
}
|
|
185
214
|
function update($$) {
|
|
186
215
|
if ($$.fragment !== null) {
|
|
@@ -215,6 +244,9 @@ function transition_out(block, local, detach, callback) {
|
|
|
215
244
|
});
|
|
216
245
|
block.o(local);
|
|
217
246
|
}
|
|
247
|
+
else if (callback) {
|
|
248
|
+
callback();
|
|
249
|
+
}
|
|
218
250
|
}
|
|
219
251
|
|
|
220
252
|
function get_spread_update(levels, updates) {
|
|
@@ -250,22 +282,27 @@ function get_spread_update(levels, updates) {
|
|
|
250
282
|
}
|
|
251
283
|
return update;
|
|
252
284
|
}
|
|
253
|
-
function mount_component(component, target, anchor) {
|
|
254
|
-
const { fragment,
|
|
285
|
+
function mount_component(component, target, anchor, customElement) {
|
|
286
|
+
const { fragment, after_update } = component.$$;
|
|
255
287
|
fragment && fragment.m(target, anchor);
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
288
|
+
if (!customElement) {
|
|
289
|
+
// onMount happens before the initial afterUpdate
|
|
290
|
+
add_render_callback(() => {
|
|
291
|
+
const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
|
|
292
|
+
// if the component was destroyed immediately
|
|
293
|
+
// it will update the `$$.on_destroy` reference to `null`.
|
|
294
|
+
// the destructured on_destroy may still reference to the old array
|
|
295
|
+
if (component.$$.on_destroy) {
|
|
296
|
+
component.$$.on_destroy.push(...new_on_destroy);
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
// Edge case - component was destroyed immediately,
|
|
300
|
+
// most likely as a result of a binding initialising
|
|
301
|
+
run_all(new_on_destroy);
|
|
302
|
+
}
|
|
303
|
+
component.$$.on_mount = [];
|
|
304
|
+
});
|
|
305
|
+
}
|
|
269
306
|
after_update.forEach(add_render_callback);
|
|
270
307
|
}
|
|
271
308
|
function destroy_component(component, detaching) {
|
|
@@ -287,12 +324,12 @@ function make_dirty(component, i) {
|
|
|
287
324
|
}
|
|
288
325
|
component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
|
|
289
326
|
}
|
|
290
|
-
function init(component, options, instance, create_fragment, not_equal, props, dirty = [-1]) {
|
|
327
|
+
function init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {
|
|
291
328
|
const parent_component = current_component;
|
|
292
329
|
set_current_component(component);
|
|
293
330
|
const $$ = component.$$ = {
|
|
294
331
|
fragment: null,
|
|
295
|
-
ctx:
|
|
332
|
+
ctx: [],
|
|
296
333
|
// state
|
|
297
334
|
props,
|
|
298
335
|
update: noop,
|
|
@@ -301,14 +338,17 @@ function init(component, options, instance, create_fragment, not_equal, props, d
|
|
|
301
338
|
// lifecycle
|
|
302
339
|
on_mount: [],
|
|
303
340
|
on_destroy: [],
|
|
341
|
+
on_disconnect: [],
|
|
304
342
|
before_update: [],
|
|
305
343
|
after_update: [],
|
|
306
|
-
context: new Map(parent_component ? parent_component.$$.context : []),
|
|
344
|
+
context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
|
|
307
345
|
// everything else
|
|
308
346
|
callbacks: blank_object(),
|
|
309
347
|
dirty,
|
|
310
|
-
skip_bound: false
|
|
348
|
+
skip_bound: false,
|
|
349
|
+
root: options.target || parent_component.$$.root
|
|
311
350
|
};
|
|
351
|
+
append_styles && append_styles($$.root);
|
|
312
352
|
let ready = false;
|
|
313
353
|
$$.ctx = instance
|
|
314
354
|
? instance(component, options.props || {}, (i, ret, ...rest) => {
|
|
@@ -340,7 +380,7 @@ function init(component, options, instance, create_fragment, not_equal, props, d
|
|
|
340
380
|
}
|
|
341
381
|
if (options.intro)
|
|
342
382
|
transition_in(component.$$.fragment);
|
|
343
|
-
mount_component(component, options.target, options.anchor);
|
|
383
|
+
mount_component(component, options.target, options.anchor, options.customElement);
|
|
344
384
|
flush();
|
|
345
385
|
}
|
|
346
386
|
set_current_component(parent_component);
|
|
@@ -354,6 +394,9 @@ class SvelteComponent {
|
|
|
354
394
|
this.$destroy = noop;
|
|
355
395
|
}
|
|
356
396
|
$on(type, callback) {
|
|
397
|
+
if (!is_function(callback)) {
|
|
398
|
+
return noop;
|
|
399
|
+
}
|
|
357
400
|
const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
|
|
358
401
|
callbacks.push(callback);
|
|
359
402
|
return () => {
|
|
@@ -397,39 +440,58 @@ function toYear(date = today()) {
|
|
|
397
440
|
return date.getFullYear().toString();
|
|
398
441
|
}
|
|
399
442
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
443
|
+
/**
|
|
444
|
+
* Formats the date, just for you!
|
|
445
|
+
*
|
|
446
|
+
* @param {Date} date - Date to format
|
|
447
|
+
* @param {'numeric' | '2-digit'} format - Format for the date.
|
|
448
|
+
*/
|
|
449
|
+
function formatDate(date = today(), format = FORMAT.NUMERIC) {
|
|
450
|
+
if (format === FORMAT.NUMERIC) {
|
|
451
|
+
return toYear(date);
|
|
452
|
+
}
|
|
453
|
+
if (format === FORMAT.TWO_DIGIT) {
|
|
454
|
+
return `’${toYear(date).slice(-2)}`;
|
|
409
455
|
}
|
|
410
456
|
}
|
|
411
457
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
458
|
+
/**
|
|
459
|
+
* Returns the "range string", unless the dates are the same.
|
|
460
|
+
*
|
|
461
|
+
* @param {string} date1 - First date (formatted to a string)
|
|
462
|
+
* @param {string} date2 - Second date (formatted to a string).
|
|
463
|
+
*/
|
|
464
|
+
function getRange(date1, date2) {
|
|
465
|
+
// Don't show a range if years are the same, as that would be dumb.
|
|
466
|
+
if (date1 === date2) {
|
|
467
|
+
return date1;
|
|
468
|
+
}
|
|
469
|
+
return `${date1} - ${date2}`;
|
|
415
470
|
}
|
|
416
471
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
472
|
+
/**
|
|
473
|
+
* Returns the displayed date for the component.
|
|
474
|
+
*
|
|
475
|
+
* @param {boolean} options.showRange - If a date range should be displayed.
|
|
476
|
+
* @param {Date} options.date - Copyright year to be used. If showRange is true, this is the start year of the range.
|
|
477
|
+
* @param {'numeric' | '2-digit'} options.format - Date format to be used.
|
|
478
|
+
*/
|
|
479
|
+
function getDisplayDate({
|
|
480
|
+
showRange = false,
|
|
481
|
+
date = today(),
|
|
482
|
+
format = FORMAT.NUMERIC,
|
|
483
|
+
}) {
|
|
484
|
+
const formatted = formatDate(date, format);
|
|
485
|
+
// Early return if we don't show the range
|
|
486
|
+
if (!showRange) {
|
|
487
|
+
return formatted;
|
|
429
488
|
}
|
|
489
|
+
// Get today's year, formatted correctly.
|
|
490
|
+
const formattedToday = formatDate(today(), format);
|
|
491
|
+
return getRange(formatted, formattedToday);
|
|
430
492
|
}
|
|
431
493
|
|
|
432
|
-
/* src/Copyright.svelte generated by Svelte v3.
|
|
494
|
+
/* src/Copyright.svelte generated by Svelte v3.54.0 */
|
|
433
495
|
|
|
434
496
|
function create_if_block_1(ctx) {
|
|
435
497
|
let t0;
|
|
@@ -452,7 +514,7 @@ function create_if_block_1(ctx) {
|
|
|
452
514
|
};
|
|
453
515
|
}
|
|
454
516
|
|
|
455
|
-
// (
|
|
517
|
+
// (27:2) {#if position === POSITION.POST}
|
|
456
518
|
function create_if_block(ctx) {
|
|
457
519
|
let t0;
|
|
458
520
|
let t1;
|
|
@@ -528,8 +590,17 @@ function create_fragment(ctx) {
|
|
|
528
590
|
}
|
|
529
591
|
|
|
530
592
|
if (default_slot) {
|
|
531
|
-
if (default_slot.p && dirty & /*$$scope*/ 64) {
|
|
532
|
-
|
|
593
|
+
if (default_slot.p && (!current || dirty & /*$$scope*/ 64)) {
|
|
594
|
+
update_slot_base(
|
|
595
|
+
default_slot,
|
|
596
|
+
default_slot_template,
|
|
597
|
+
ctx,
|
|
598
|
+
/*$$scope*/ ctx[6],
|
|
599
|
+
!current
|
|
600
|
+
? get_all_dirty_from_scope(/*$$scope*/ ctx[6])
|
|
601
|
+
: get_slot_changes(default_slot_template, /*$$scope*/ ctx[6], dirty, null),
|
|
602
|
+
null
|
|
603
|
+
);
|
|
533
604
|
}
|
|
534
605
|
}
|
|
535
606
|
|
|
@@ -570,25 +641,22 @@ function instance($$self, $$props, $$invalidate) {
|
|
|
570
641
|
const omit_props_names = ["date","format","position","showRange"];
|
|
571
642
|
let $$restProps = compute_rest_props($$props, omit_props_names);
|
|
572
643
|
let { $$slots: slots = {}, $$scope } = $$props;
|
|
573
|
-
let { date =
|
|
644
|
+
let { date = today() } = $$props;
|
|
574
645
|
let { format = FORMAT.NUMERIC } = $$props;
|
|
575
646
|
let { position = POSITION.PRE } = $$props;
|
|
576
647
|
let { showRange = false } = $$props;
|
|
577
648
|
|
|
578
649
|
// Get the formatDate function
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
const getDateRange = withGetDateRange(showRange);
|
|
582
|
-
let displayDate = getDateRange(date, formatDate);
|
|
650
|
+
let displayDate = getDisplayDate({ showRange, format, date });
|
|
583
651
|
|
|
584
652
|
$$self.$$set = $$new_props => {
|
|
585
653
|
$$props = assign(assign({}, $$props), exclude_internal_props($$new_props));
|
|
586
654
|
$$invalidate(2, $$restProps = compute_rest_props($$props, omit_props_names));
|
|
587
|
-
if (
|
|
588
|
-
if (
|
|
589
|
-
if (
|
|
590
|
-
if (
|
|
591
|
-
if (
|
|
655
|
+
if ('date' in $$new_props) $$invalidate(3, date = $$new_props.date);
|
|
656
|
+
if ('format' in $$new_props) $$invalidate(4, format = $$new_props.format);
|
|
657
|
+
if ('position' in $$new_props) $$invalidate(0, position = $$new_props.position);
|
|
658
|
+
if ('showRange' in $$new_props) $$invalidate(5, showRange = $$new_props.showRange);
|
|
659
|
+
if ('$$scope' in $$new_props) $$invalidate(6, $$scope = $$new_props.$$scope);
|
|
592
660
|
};
|
|
593
661
|
|
|
594
662
|
return [position, displayDate, $$restProps, date, format, showRange, $$scope, slots];
|
|
@@ -607,5 +675,6 @@ class Copyright extends SvelteComponent {
|
|
|
607
675
|
}
|
|
608
676
|
}
|
|
609
677
|
|
|
610
|
-
|
|
611
|
-
|
|
678
|
+
var Copyright$1 = Copyright;
|
|
679
|
+
|
|
680
|
+
export { constants, Copyright$1 as default };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-copyright",
|
|
3
3
|
"description": "A Svelte component to format and display a copyright notice.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "himynameisdave",
|
|
7
7
|
"email": "d@velunny.com",
|
|
@@ -15,24 +15,25 @@
|
|
|
15
15
|
"lib"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "rollup -c",
|
|
18
|
+
"build": "rollup -c --bundleConfigAsCjs",
|
|
19
19
|
"test": "jest src",
|
|
20
20
|
"release": "np --no-yarn"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@babel/core": "^7.
|
|
24
|
-
"@babel/preset-env": "^7.
|
|
25
|
-
"@rollup/plugin-node-resolve": "^
|
|
26
|
-
"@testing-library/jest-dom": "^5.
|
|
27
|
-
"@testing-library/svelte": "^3.
|
|
28
|
-
"babel-jest": "^
|
|
29
|
-
"husky": "^
|
|
30
|
-
"jest": "^
|
|
31
|
-
"
|
|
32
|
-
"
|
|
23
|
+
"@babel/core": "^7.20.5",
|
|
24
|
+
"@babel/preset-env": "^7.20.2",
|
|
25
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
26
|
+
"@testing-library/jest-dom": "^5.16.5",
|
|
27
|
+
"@testing-library/svelte": "^3.2.2",
|
|
28
|
+
"babel-jest": "^29.3.1",
|
|
29
|
+
"husky": "^8.0.2",
|
|
30
|
+
"jest": "^29.3.1",
|
|
31
|
+
"jest-environment-jsdom": "^29.3.1",
|
|
32
|
+
"np": "^7.6.2",
|
|
33
|
+
"rollup": "^3.7.3",
|
|
33
34
|
"rollup-plugin-svelte": "^7.1.0",
|
|
34
|
-
"svelte": "^3.
|
|
35
|
-
"svelte-jester": "^
|
|
35
|
+
"svelte": "^3.54.0",
|
|
36
|
+
"svelte-jester": "^2.3.2"
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|
|
38
39
|
"svelte": "^3.0.0"
|
package/src/Copyright.svelte
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { FORMAT, POSITION } from './constants';
|
|
3
|
-
import {
|
|
3
|
+
import { getDisplayDate, today } from './utils';
|
|
4
4
|
|
|
5
5
|
// The date year to be displayed (default: today)
|
|
6
|
-
export let date =
|
|
6
|
+
export let date = today();
|
|
7
7
|
// Date format ('numeric' | '2-digit')
|
|
8
8
|
export let format = FORMAT.NUMERIC;
|
|
9
9
|
// Position of the copyright + date message relative to component "children" slot.
|
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
export let showRange = false;
|
|
13
13
|
|
|
14
14
|
// Get the formatDate function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
let displayDate = getDisplayDate({
|
|
16
|
+
showRange,
|
|
17
|
+
format,
|
|
18
|
+
date,
|
|
19
|
+
});
|
|
19
20
|
</script>
|
|
20
21
|
|
|
21
22
|
<span {...$$restProps}>
|
|
@@ -1,60 +1,58 @@
|
|
|
1
|
-
import '@testing-library/jest-dom/extend-expect';
|
|
2
1
|
import { render } from '@testing-library/svelte';
|
|
3
2
|
import Copyright from './Copyright.spec.svelte';
|
|
4
3
|
|
|
4
|
+
const FIXED_DATE = new Date('2022-05-29');
|
|
5
|
+
const FIXED_YEAR = FIXED_DATE.getFullYear();
|
|
5
6
|
|
|
6
7
|
// Get around some of the stupidity of this testing library
|
|
7
8
|
function renderCopyright(props = {}) {
|
|
8
|
-
// Fixed date so that tests don't fail next year.
|
|
9
|
-
const fixedDate = new Date('2021-05-29');
|
|
10
9
|
const { container } = render(Copyright, {
|
|
11
|
-
date:
|
|
10
|
+
date: FIXED_DATE,
|
|
12
11
|
...props,
|
|
13
12
|
});
|
|
14
13
|
return container.firstChild.firstChild;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
describe('<Copyright />', () => {
|
|
18
|
-
|
|
19
|
-
test('it uses the provided date for the year', () => {
|
|
17
|
+
it('uses the provided date for the year', () => {
|
|
20
18
|
const container = renderCopyright({ date: new Date(1990, 0, 1) });
|
|
21
19
|
expect(container).toHaveTextContent('© Copyright 1990 Dave Lunny');
|
|
22
20
|
});
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
it('formats the year for format="numeric"', () => {
|
|
25
23
|
const container = renderCopyright({ format: 'numeric' });
|
|
26
|
-
expect(container).toHaveTextContent(
|
|
24
|
+
expect(container).toHaveTextContent(`© Copyright ${FIXED_YEAR} Dave Lunny`);
|
|
27
25
|
});
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
it('formats the year for format="2-digit"', () => {
|
|
30
28
|
const container = renderCopyright({ format: '2-digit' });
|
|
31
|
-
expect(container).toHaveTextContent(
|
|
29
|
+
expect(container).toHaveTextContent(`© Copyright ’${FIXED_YEAR.toString().slice(2)} Dave Lunny`);
|
|
32
30
|
});
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
it('positions the copyright for position="pre"', () => {
|
|
35
33
|
const container = renderCopyright({ position: 'pre' });
|
|
36
|
-
expect(container).toHaveTextContent(
|
|
34
|
+
expect(container).toHaveTextContent(`© Copyright ${FIXED_YEAR} Dave Lunny`);
|
|
37
35
|
});
|
|
38
36
|
|
|
39
|
-
|
|
37
|
+
it('positions the copyright for position="post"', () => {
|
|
40
38
|
const container = renderCopyright({ position: 'post' });
|
|
41
|
-
expect(container).toHaveTextContent(
|
|
39
|
+
expect(container).toHaveTextContent(`Dave Lunny © Copyright ${FIXED_YEAR}`);
|
|
42
40
|
});
|
|
43
41
|
|
|
44
|
-
|
|
42
|
+
it('displays a date range when showRange=true', () => {
|
|
45
43
|
const container = renderCopyright({
|
|
46
44
|
date: new Date(1990, 0, 1),
|
|
47
45
|
showRange: true,
|
|
48
46
|
});
|
|
49
|
-
expect(container).toHaveTextContent(
|
|
47
|
+
expect(container).toHaveTextContent(`© Copyright 1990 - ${FIXED_YEAR} Dave Lunny`);
|
|
50
48
|
});
|
|
51
49
|
|
|
52
|
-
|
|
50
|
+
it('showRange=true but no date is provided, just display current year', () => {
|
|
53
51
|
const container = renderCopyright({ showRange: true });
|
|
54
|
-
expect(container).toHaveTextContent(
|
|
52
|
+
expect(container).toHaveTextContent(`© Copyright ${FIXED_YEAR} Dave Lunny`);
|
|
55
53
|
});
|
|
56
54
|
|
|
57
|
-
|
|
55
|
+
it('spreads the rest of the props correctly', () => {
|
|
58
56
|
const mockCustomClass = 'custom-class';
|
|
59
57
|
const container = renderCopyright({ class: mockCustomClass });
|
|
60
58
|
expect(container.classList.contains('custom-class')).toBe(true);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as dateUtils from '../date';
|
|
2
2
|
import * as constants from '../../constants';
|
|
3
3
|
|
|
4
|
-
|
|
5
4
|
describe('utils/date', () => {
|
|
6
5
|
const mockDate = new Date('1990-08-08');
|
|
6
|
+
const currentYear = dateUtils.today().getFullYear();
|
|
7
7
|
|
|
8
8
|
describe('toYear', () => {
|
|
9
9
|
it('returns the year value for a given date', () => {
|
|
@@ -12,36 +12,77 @@ describe('utils/date', () => {
|
|
|
12
12
|
});
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
-
describe('
|
|
15
|
+
describe('formatDate', () => {
|
|
16
16
|
it('handles formatting a "numeric" year', () => {
|
|
17
|
-
const
|
|
18
|
-
const actual = formatDate(mockDate);
|
|
17
|
+
const actual = dateUtils.formatDate(mockDate, constants.FORMAT.NUMERIC);
|
|
19
18
|
expect(actual).toBe('1990');
|
|
20
19
|
});
|
|
20
|
+
|
|
21
21
|
it('handles formatting a "2-digit" year', () => {
|
|
22
|
-
const
|
|
23
|
-
const actual = formatDate(mockDate);
|
|
22
|
+
const actual = dateUtils.formatDate(mockDate, constants.FORMAT.TWO_DIGIT);
|
|
24
23
|
expect(actual).toBe('’90');
|
|
25
24
|
});
|
|
25
|
+
|
|
26
|
+
it('does nothing if invalid format is passed', () => {
|
|
27
|
+
const actual = dateUtils.formatDate(mockDate, 'haha wrong!');
|
|
28
|
+
expect(actual).toBeUndefined();
|
|
29
|
+
});
|
|
26
30
|
});
|
|
27
31
|
|
|
28
|
-
describe('
|
|
29
|
-
it('
|
|
30
|
-
const
|
|
31
|
-
const actual =
|
|
32
|
-
expect(actual).toBe(
|
|
32
|
+
describe('getRange', () => {
|
|
33
|
+
it('returns the first date if it is the same as second', () => {
|
|
34
|
+
const year = dateUtils.toYear(mockDate);
|
|
35
|
+
const actual = dateUtils.getRange(year, year);
|
|
36
|
+
expect(actual).toBe(year);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('returns the range string if different years', () => {
|
|
40
|
+
const year1 = dateUtils.toYear(mockDate);
|
|
41
|
+
const year2 = dateUtils.toYear(dateUtils.today());
|
|
42
|
+
const actual = dateUtils.getRange(year1, year2);
|
|
43
|
+
expect(actual).toBe(`${year1} - ${year2}`);
|
|
33
44
|
});
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('getDisplayDate', () => {
|
|
48
|
+
describe('when showRange is true', () => {
|
|
49
|
+
it('handles formatting a "numeric" year', () => {
|
|
50
|
+
const actual = dateUtils.getDisplayDate({
|
|
51
|
+
showRange: true,
|
|
52
|
+
format: constants.FORMAT.NUMERIC,
|
|
53
|
+
date: mockDate,
|
|
54
|
+
});
|
|
55
|
+
expect(actual).toBe(`1990 - ${currentYear}`);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('handles formatting a "2-digit" year', () => {
|
|
59
|
+
const actual = dateUtils.getDisplayDate({
|
|
60
|
+
showRange: true,
|
|
61
|
+
format: constants.FORMAT.TWO_DIGIT,
|
|
62
|
+
date: mockDate,
|
|
63
|
+
});
|
|
64
|
+
expect(actual).toBe(`’90 - ’${currentYear.toString().slice(2)}`);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('when showRange is false', () => {
|
|
69
|
+
it('handles formatting a "numeric" year', () => {
|
|
70
|
+
const actual = dateUtils.getDisplayDate({
|
|
71
|
+
showRange: false,
|
|
72
|
+
format: constants.FORMAT.NUMERIC,
|
|
73
|
+
date: mockDate,
|
|
74
|
+
});
|
|
75
|
+
expect(actual).toBe('1990');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('handles formatting a "2-digit" year', () => {
|
|
79
|
+
const actual = dateUtils.getDisplayDate({
|
|
80
|
+
showRange: false,
|
|
81
|
+
format: constants.FORMAT.TWO_DIGIT,
|
|
82
|
+
date: mockDate,
|
|
83
|
+
});
|
|
84
|
+
expect(actual).toBe('’90');
|
|
85
|
+
});
|
|
45
86
|
});
|
|
46
87
|
});
|
|
47
88
|
});
|
package/src/utils/date.js
CHANGED
|
@@ -10,34 +10,53 @@ export function toYear(date = today()) {
|
|
|
10
10
|
return date.getFullYear().toString();
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Formats the date, just for you!
|
|
15
|
+
*
|
|
16
|
+
* @param {Date} date - Date to format
|
|
17
|
+
* @param {'numeric' | '2-digit'} format - Format for the date.
|
|
18
|
+
*/
|
|
19
|
+
export function formatDate(date = today(), format = FORMAT.NUMERIC) {
|
|
20
|
+
if (format === FORMAT.NUMERIC) {
|
|
21
|
+
return toYear(date);
|
|
22
|
+
}
|
|
23
|
+
if (format === FORMAT.TWO_DIGIT) {
|
|
24
|
+
return `’${toYear(date).slice(-2)}`;
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Returns the "range string", unless the dates are the same.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} date1 - First date (formatted to a string)
|
|
32
|
+
* @param {string} date2 - Second date (formatted to a string).
|
|
33
|
+
*/
|
|
34
|
+
export function getRange(date1, date2) {
|
|
35
|
+
// Don't show a range if years are the same, as that would be dumb.
|
|
36
|
+
if (date1 === date2) {
|
|
37
|
+
return date1;
|
|
38
|
+
}
|
|
39
|
+
return `${date1} - ${date2}`;
|
|
28
40
|
}
|
|
29
41
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Returns the displayed date for the component.
|
|
44
|
+
*
|
|
45
|
+
* @param {boolean} options.showRange - If a date range should be displayed.
|
|
46
|
+
* @param {Date} options.date - Copyright year to be used. If showRange is true, this is the start year of the range.
|
|
47
|
+
* @param {'numeric' | '2-digit'} options.format - Date format to be used.
|
|
48
|
+
*/
|
|
49
|
+
export function getDisplayDate({
|
|
50
|
+
showRange = false,
|
|
51
|
+
date = today(),
|
|
52
|
+
format = FORMAT.NUMERIC,
|
|
53
|
+
}) {
|
|
54
|
+
const formatted = formatDate(date, format);
|
|
55
|
+
// Early return if we don't show the range
|
|
56
|
+
if (!showRange) {
|
|
57
|
+
return formatted;
|
|
42
58
|
}
|
|
59
|
+
// Get today's year, formatted correctly.
|
|
60
|
+
const formattedToday = formatDate(today(), format);
|
|
61
|
+
return getRange(formatted, formattedToday);
|
|
43
62
|
}
|
package/src/utils/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { getDisplayDate, today } from './date';
|