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 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://travis-ci.com/github/himynameisdave/svelte-copyright'>
6
- <img src="https://travis-ci.com/himynameisdave/svelte-copyright.svg?token=NSWKYfhiSswtVimc1js9&branch=master&status=passed" alt="Travis Badge" />
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 update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {
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.removeChild(node);
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
- let flushing = false;
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
- if (flushing)
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
- for (let i = 0; i < dirty_components.length; i += 1) {
163
- const component = dirty_components[i];
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, on_mount, on_destroy, after_update } = component.$$;
291
+ function mount_component(component, target, anchor, customElement) {
292
+ const { fragment, after_update } = component.$$;
261
293
  fragment && fragment.m(target, anchor);
262
- // onMount happens before the initial afterUpdate
263
- add_render_callback(() => {
264
- const new_on_destroy = on_mount.map(run).filter(is_function);
265
- if (on_destroy) {
266
- on_destroy.push(...new_on_destroy);
267
- }
268
- else {
269
- // Edge case - component was destroyed immediately,
270
- // most likely as a result of a binding initialising
271
- run_all(new_on_destroy);
272
- }
273
- component.$$.on_mount = [];
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: null,
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
- // HOF which is injected with the format and returns the date formatter function.
407
- function withFormatGetDate(format = FORMAT.NUMERIC) {
408
- return function formatDate(date = today()) {
409
- if (format === FORMAT.NUMERIC) {
410
- return toYear(date);
411
- }
412
- if (format === FORMAT.TWO_DIGIT) {
413
- return `’${toYear(date).slice(-2)}`;
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
- // A default for the getDateRange formatter.
419
- function defaultFormatDate(date) {
420
- return date;
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
- // HOF which is injected with the showRange and returns a getDateRange function.
424
- function withGetDateRange(showRange = false) {
425
- return function getDateRange(date = today(), formatDate = defaultFormatDate) {
426
- const formattedToday = formatDate(today());
427
- const formattedDate = formatDate(date);
428
- if (showRange && formattedToday !== formattedDate) { // Make sure that if it's a range, the two years aren't the same.
429
- return [
430
- formattedDate,
431
- formattedToday
432
- ].join(' - ');
433
- }
434
- return formattedDate;
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.32.1 */
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
- // (26:2) {#if position === POSITION.POST}
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
- update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[6], dirty, null, null);
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 = new Date() } = $$props;
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
- const formatDate = withFormatGetDate(format);
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 ("date" in $$new_props) $$invalidate(3, date = $$new_props.date);
594
- if ("format" in $$new_props) $$invalidate(4, format = $$new_props.format);
595
- if ("position" in $$new_props) $$invalidate(0, position = $$new_props.position);
596
- if ("showRange" in $$new_props) $$invalidate(5, showRange = $$new_props.showRange);
597
- if ("$$scope" in $$new_props) $$invalidate(6, $$scope = $$new_props.$$scope);
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 update_slot(slot, slot_definition, ctx, $$scope, dirty, get_slot_changes_fn, get_slot_context_fn) {
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.removeChild(node);
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
- let flushing = false;
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
- if (flushing)
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
- for (let i = 0; i < dirty_components.length; i += 1) {
157
- const component = dirty_components[i];
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, on_mount, on_destroy, after_update } = component.$$;
285
+ function mount_component(component, target, anchor, customElement) {
286
+ const { fragment, after_update } = component.$$;
255
287
  fragment && fragment.m(target, anchor);
256
- // onMount happens before the initial afterUpdate
257
- add_render_callback(() => {
258
- const new_on_destroy = on_mount.map(run).filter(is_function);
259
- if (on_destroy) {
260
- on_destroy.push(...new_on_destroy);
261
- }
262
- else {
263
- // Edge case - component was destroyed immediately,
264
- // most likely as a result of a binding initialising
265
- run_all(new_on_destroy);
266
- }
267
- component.$$.on_mount = [];
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: null,
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
- // HOF which is injected with the format and returns the date formatter function.
401
- function withFormatGetDate(format = FORMAT.NUMERIC) {
402
- return function formatDate(date = today()) {
403
- if (format === FORMAT.NUMERIC) {
404
- return toYear(date);
405
- }
406
- if (format === FORMAT.TWO_DIGIT) {
407
- return `’${toYear(date).slice(-2)}`;
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
- // A default for the getDateRange formatter.
413
- function defaultFormatDate(date) {
414
- return date;
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
- // HOF which is injected with the showRange and returns a getDateRange function.
418
- function withGetDateRange(showRange = false) {
419
- return function getDateRange(date = today(), formatDate = defaultFormatDate) {
420
- const formattedToday = formatDate(today());
421
- const formattedDate = formatDate(date);
422
- if (showRange && formattedToday !== formattedDate) { // Make sure that if it's a range, the two years aren't the same.
423
- return [
424
- formattedDate,
425
- formattedToday
426
- ].join(' - ');
427
- }
428
- return formattedDate;
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.32.1 */
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
- // (26:2) {#if position === POSITION.POST}
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
- update_slot(default_slot, default_slot_template, ctx, /*$$scope*/ ctx[6], dirty, null, null);
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 = new Date() } = $$props;
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
- const formatDate = withFormatGetDate(format);
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 ("date" in $$new_props) $$invalidate(3, date = $$new_props.date);
588
- if ("format" in $$new_props) $$invalidate(4, format = $$new_props.format);
589
- if ("position" in $$new_props) $$invalidate(0, position = $$new_props.position);
590
- if ("showRange" in $$new_props) $$invalidate(5, showRange = $$new_props.showRange);
591
- if ("$$scope" in $$new_props) $$invalidate(6, $$scope = $$new_props.$$scope);
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
- export default Copyright;
611
- export { constants };
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.1.3",
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.12.10",
24
- "@babel/preset-env": "^7.12.11",
25
- "@rollup/plugin-node-resolve": "^11.1.1",
26
- "@testing-library/jest-dom": "^5.11.9",
27
- "@testing-library/svelte": "^3.0.3",
28
- "babel-jest": "^26.6.3",
29
- "husky": "^4.3.8",
30
- "jest": "^26.6.3",
31
- "np": "^7.2.0",
32
- "rollup": "^2.38.2",
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.32.1",
35
- "svelte-jester": "^1.3.0"
35
+ "svelte": "^3.54.0",
36
+ "svelte-jester": "^2.3.2"
36
37
  },
37
38
  "peerDependencies": {
38
39
  "svelte": "^3.0.0"
@@ -1,9 +1,9 @@
1
1
  <script>
2
2
  import { FORMAT, POSITION } from './constants';
3
- import { withFormatGetDate, withGetDateRange } from './utils';
3
+ import { getDisplayDate, today } from './utils';
4
4
 
5
5
  // The date year to be displayed (default: today)
6
- export let date = new 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
- const formatDate = withFormatGetDate(format);
16
- const getDateRange = withGetDateRange(showRange);
17
-
18
- let displayDate = getDateRange(date, formatDate);
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: fixedDate,
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
- test('it formats the year for format="numeric"', () => {
22
+ it('formats the year for format="numeric"', () => {
25
23
  const container = renderCopyright({ format: 'numeric' });
26
- expect(container).toHaveTextContent( Copyright 2021 Dave Lunny');
24
+ expect(container).toHaveTextContent( Copyright ${FIXED_YEAR} Dave Lunny`);
27
25
  });
28
26
 
29
- test('it formats the year for format="2-digit"', () => {
27
+ it('formats the year for format="2-digit"', () => {
30
28
  const container = renderCopyright({ format: '2-digit' });
31
- expect(container).toHaveTextContent( Copyright ’21 Dave Lunny');
29
+ expect(container).toHaveTextContent( Copyright ’${FIXED_YEAR.toString().slice(2)} Dave Lunny`);
32
30
  });
33
31
 
34
- test('it positions the copyright for position="pre"', () => {
32
+ it('positions the copyright for position="pre"', () => {
35
33
  const container = renderCopyright({ position: 'pre' });
36
- expect(container).toHaveTextContent( Copyright 2021 Dave Lunny');
34
+ expect(container).toHaveTextContent( Copyright ${FIXED_YEAR} Dave Lunny`);
37
35
  });
38
36
 
39
- test('it positions the copyright for position="post"', () => {
37
+ it('positions the copyright for position="post"', () => {
40
38
  const container = renderCopyright({ position: 'post' });
41
- expect(container).toHaveTextContent('Dave Lunny © Copyright 2021');
39
+ expect(container).toHaveTextContent(`Dave Lunny © Copyright ${FIXED_YEAR}`);
42
40
  });
43
41
 
44
- test('it displays a date range when showRange=true', () => {
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( Copyright 1990 - 2021 Dave Lunny');
47
+ expect(container).toHaveTextContent( Copyright 1990 - ${FIXED_YEAR} Dave Lunny`);
50
48
  });
51
49
 
52
- test('if showRange=true but no date is provided, just display current year', () => {
50
+ it('showRange=true but no date is provided, just display current year', () => {
53
51
  const container = renderCopyright({ showRange: true });
54
- expect(container).toHaveTextContent( Copyright 2021 Dave Lunny');
52
+ expect(container).toHaveTextContent( Copyright ${FIXED_YEAR} Dave Lunny`);
55
53
  });
56
54
 
57
- test('it spreads the rest of the props correctly', () => {
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('withFormatGetDate', () => {
15
+ describe('formatDate', () => {
16
16
  it('handles formatting a "numeric" year', () => {
17
- const formatDate = dateUtils.withFormatGetDate(constants.FORMAT.NUMERIC);
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 formatDate = dateUtils.withFormatGetDate(constants.FORMAT.TWO_DIGIT);
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('withGetDateRange', () => {
29
- it('it will just return the year when showRange is false', () => {
30
- const getDateRange = dateUtils.withGetDateRange(false);
31
- const actual = getDateRange(mockDate, dateUtils.toYear);
32
- expect(actual).toBe('1990');
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
- // TODO: this test will break in 2022
35
- it('it will return the date range when showRange is true', () => {
36
- const getDateRange = dateUtils.withGetDateRange(true);
37
- const actual = getDateRange(mockDate, dateUtils.toYear);
38
- expect(actual).toBe('1990 - 2021');
39
- });
40
- // TODO: this test will break in 2022
41
- it('it will return the year when showRange is true, but the given year is the current year', () => {
42
- const getDateRange = dateUtils.withGetDateRange(true);
43
- const actual = getDateRange(undefined, dateUtils.toYear);
44
- expect(actual).toBe('2021');
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
- // HOF which is injected with the format and returns the date formatter function.
14
- export function withFormatGetDate(format = FORMAT.NUMERIC) {
15
- return function formatDate(date = today()) {
16
- if (format === FORMAT.NUMERIC) {
17
- return toYear(date);
18
- }
19
- if (format === FORMAT.TWO_DIGIT) {
20
- return `’${toYear(date).slice(-2)}`;
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
- // A default for the getDateRange formatter.
26
- function defaultFormatDate(date) {
27
- return date;
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
- // HOF which is injected with the showRange and returns a getDateRange function.
31
- export function withGetDateRange(showRange = false) {
32
- return function getDateRange(date = today(), formatDate = defaultFormatDate) {
33
- const formattedToday = formatDate(today());
34
- const formattedDate = formatDate(date);
35
- if (showRange && formattedToday !== formattedDate) { // Make sure that if it's a range, the two years aren't the same.
36
- return [
37
- formattedDate,
38
- formattedToday
39
- ].join(' - ');
40
- }
41
- return formattedDate;
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
  }
@@ -1 +1 @@
1
- export { withFormatGetDate, withGetDateRange } from './date';
1
+ export { getDisplayDate, today } from './date';