govuk_publishing_components 43.0.1 → 43.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +39 -17
  3. data/app/assets/stylesheets/component_guide/application.scss +1 -1
  4. data/app/assets/stylesheets/govuk_publishing_components/components/_cross-service-header.scss +3 -1
  5. data/app/assets/stylesheets/govuk_publishing_components/components/_intervention.scss +1 -1
  6. data/app/assets/stylesheets/govuk_publishing_components/components/_inverse-header.scss +3 -1
  7. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-footer.scss +32 -3
  8. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-header.scss +1 -3
  9. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +1 -1
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_metadata.scss +1 -1
  11. data/app/assets/stylesheets/govuk_publishing_components/components/_phase-banner.scss +1 -1
  12. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav-header.scss +1 -1
  13. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav-related.scss +1 -1
  14. data/app/assets/stylesheets/govuk_publishing_components/components/_success-alert.scss +1 -1
  15. data/app/assets/stylesheets/govuk_publishing_components/components/_table.scss +1 -1
  16. data/app/assets/stylesheets/govuk_publishing_components/components/_warning-text.scss +1 -1
  17. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_button.scss +1 -1
  18. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_highlight-answer.scss +2 -4
  19. data/app/assets/stylesheets/govuk_publishing_components/govuk_frontend_support.scss +4 -0
  20. data/app/views/govuk_publishing_components/components/_layout_footer.html.erb +1 -1
  21. data/app/views/govuk_publishing_components/components/layout_header/_navigation_items.html.erb +6 -3
  22. data/app/views/govuk_publishing_components/components/layout_header/_search.html.erb +7 -2
  23. data/lib/govuk_publishing_components/version.rb +1 -1
  24. data/node_modules/sortablejs/README.md +3 -2
  25. data/node_modules/sortablejs/Sortable.js +5 -4
  26. data/node_modules/sortablejs/Sortable.min.js +2 -2
  27. data/node_modules/sortablejs/modular/sortable.complete.esm.js +5 -4
  28. data/node_modules/sortablejs/modular/sortable.core.esm.js +5 -4
  29. data/node_modules/sortablejs/modular/sortable.esm.js +5 -4
  30. data/node_modules/sortablejs/package.json +3 -2
  31. data/node_modules/sortablejs/src/Animation.js +175 -0
  32. data/node_modules/sortablejs/src/BrowserInfo.js +12 -0
  33. data/node_modules/sortablejs/src/EventDispatcher.js +57 -0
  34. data/node_modules/sortablejs/src/PluginManager.js +94 -0
  35. data/node_modules/sortablejs/src/Sortable.js +2011 -0
  36. data/node_modules/sortablejs/src/utils.js +595 -0
  37. metadata +8 -2
@@ -0,0 +1,595 @@
1
+ import { IE11OrLess } from './BrowserInfo.js';
2
+ import Sortable from './Sortable.js';
3
+
4
+ const captureMode = {
5
+ capture: false,
6
+ passive: false
7
+ };
8
+
9
+ function on(el, event, fn) {
10
+ el.addEventListener(event, fn, !IE11OrLess && captureMode);
11
+ }
12
+
13
+
14
+ function off(el, event, fn) {
15
+ el.removeEventListener(event, fn, !IE11OrLess && captureMode);
16
+ }
17
+
18
+ function matches(/**HTMLElement*/el, /**String*/selector) {
19
+ if (!selector) return;
20
+
21
+ selector[0] === '>' && (selector = selector.substring(1));
22
+
23
+ if (el) {
24
+ try {
25
+ if (el.matches) {
26
+ return el.matches(selector);
27
+ } else if (el.msMatchesSelector) {
28
+ return el.msMatchesSelector(selector);
29
+ } else if (el.webkitMatchesSelector) {
30
+ return el.webkitMatchesSelector(selector);
31
+ }
32
+ } catch(_) {
33
+ return false;
34
+ }
35
+ }
36
+
37
+ return false;
38
+ }
39
+
40
+ function getParentOrHost(el) {
41
+ return (el.host && el !== document && el.host.nodeType)
42
+ ? el.host
43
+ : el.parentNode;
44
+ }
45
+
46
+ function closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx, includeCTX) {
47
+ if (el) {
48
+ ctx = ctx || document;
49
+
50
+ do {
51
+ if (
52
+ selector != null &&
53
+ (
54
+ selector[0] === '>' ?
55
+ el.parentNode === ctx && matches(el, selector) :
56
+ matches(el, selector)
57
+ ) ||
58
+ includeCTX && el === ctx
59
+ ) {
60
+ return el;
61
+ }
62
+
63
+ if (el === ctx) break;
64
+ /* jshint boss:true */
65
+ } while (el = getParentOrHost(el));
66
+ }
67
+
68
+ return null;
69
+ }
70
+
71
+ const R_SPACE = /\s+/g;
72
+
73
+ function toggleClass(el, name, state) {
74
+ if (el && name) {
75
+ if (el.classList) {
76
+ el.classList[state ? 'add' : 'remove'](name);
77
+ }
78
+ else {
79
+ let className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
80
+ el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
81
+ }
82
+ }
83
+ }
84
+
85
+
86
+ function css(el, prop, val) {
87
+ let style = el && el.style;
88
+
89
+ if (style) {
90
+ if (val === void 0) {
91
+ if (document.defaultView && document.defaultView.getComputedStyle) {
92
+ val = document.defaultView.getComputedStyle(el, '');
93
+ }
94
+ else if (el.currentStyle) {
95
+ val = el.currentStyle;
96
+ }
97
+
98
+ return prop === void 0 ? val : val[prop];
99
+ }
100
+ else {
101
+ if (!(prop in style) && prop.indexOf('webkit') === -1) {
102
+ prop = '-webkit-' + prop;
103
+ }
104
+
105
+ style[prop] = val + (typeof val === 'string' ? '' : 'px');
106
+ }
107
+ }
108
+ }
109
+
110
+ function matrix(el, selfOnly) {
111
+ let appliedTransforms = '';
112
+ if (typeof(el) === 'string') {
113
+ appliedTransforms = el;
114
+ } else {
115
+ do {
116
+ let transform = css(el, 'transform');
117
+
118
+ if (transform && transform !== 'none') {
119
+ appliedTransforms = transform + ' ' + appliedTransforms;
120
+ }
121
+ /* jshint boss:true */
122
+ } while (!selfOnly && (el = el.parentNode));
123
+ }
124
+
125
+ const matrixFn = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix;
126
+ /*jshint -W056 */
127
+ return matrixFn && (new matrixFn(appliedTransforms));
128
+ }
129
+
130
+
131
+ function find(ctx, tagName, iterator) {
132
+ if (ctx) {
133
+ let list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;
134
+
135
+ if (iterator) {
136
+ for (; i < n; i++) {
137
+ iterator(list[i], i);
138
+ }
139
+ }
140
+
141
+ return list;
142
+ }
143
+
144
+ return [];
145
+ }
146
+
147
+
148
+
149
+ function getWindowScrollingElement() {
150
+ let scrollingElement = document.scrollingElement;
151
+
152
+ if (scrollingElement) {
153
+ return scrollingElement
154
+ } else {
155
+ return document.documentElement
156
+ }
157
+ }
158
+
159
+
160
+ /**
161
+ * Returns the "bounding client rect" of given element
162
+ * @param {HTMLElement} el The element whose boundingClientRect is wanted
163
+ * @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container
164
+ * @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr
165
+ * @param {[Boolean]} undoScale Whether the container's scale() should be undone
166
+ * @param {[HTMLElement]} container The parent the element will be placed in
167
+ * @return {Object} The boundingClientRect of el, with specified adjustments
168
+ */
169
+ function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) {
170
+ if (!el.getBoundingClientRect && el !== window) return;
171
+
172
+ let elRect,
173
+ top,
174
+ left,
175
+ bottom,
176
+ right,
177
+ height,
178
+ width;
179
+
180
+ if (el !== window && el.parentNode && el !== getWindowScrollingElement()) {
181
+ elRect = el.getBoundingClientRect();
182
+ top = elRect.top;
183
+ left = elRect.left;
184
+ bottom = elRect.bottom;
185
+ right = elRect.right;
186
+ height = elRect.height;
187
+ width = elRect.width;
188
+ } else {
189
+ top = 0;
190
+ left = 0;
191
+ bottom = window.innerHeight;
192
+ right = window.innerWidth;
193
+ height = window.innerHeight;
194
+ width = window.innerWidth;
195
+ }
196
+
197
+ if ((relativeToContainingBlock || relativeToNonStaticParent) && el !== window) {
198
+ // Adjust for translate()
199
+ container = container || el.parentNode;
200
+
201
+ // solves #1123 (see: https://stackoverflow.com/a/37953806/6088312)
202
+ // Not needed on <= IE11
203
+ if (!IE11OrLess) {
204
+ do {
205
+ if (
206
+ container &&
207
+ container.getBoundingClientRect &&
208
+ (
209
+ css(container, 'transform') !== 'none' ||
210
+ relativeToNonStaticParent &&
211
+ css(container, 'position') !== 'static'
212
+ )
213
+ ) {
214
+ let containerRect = container.getBoundingClientRect();
215
+
216
+ // Set relative to edges of padding box of container
217
+ top -= containerRect.top + parseInt(css(container, 'border-top-width'));
218
+ left -= containerRect.left + parseInt(css(container, 'border-left-width'));
219
+ bottom = top + elRect.height;
220
+ right = left + elRect.width;
221
+
222
+ break;
223
+ }
224
+ /* jshint boss:true */
225
+ } while (container = container.parentNode);
226
+ }
227
+ }
228
+
229
+ if (undoScale && el !== window) {
230
+ // Adjust for scale()
231
+ let elMatrix = matrix(container || el),
232
+ scaleX = elMatrix && elMatrix.a,
233
+ scaleY = elMatrix && elMatrix.d;
234
+
235
+ if (elMatrix) {
236
+ top /= scaleY;
237
+ left /= scaleX;
238
+
239
+ width /= scaleX;
240
+ height /= scaleY;
241
+
242
+ bottom = top + height;
243
+ right = left + width;
244
+ }
245
+ }
246
+
247
+ return {
248
+ top: top,
249
+ left: left,
250
+ bottom: bottom,
251
+ right: right,
252
+ width: width,
253
+ height: height
254
+ };
255
+ }
256
+
257
+ /**
258
+ * Returns the content rect of the element (bounding rect minus border and padding)
259
+ * @param {HTMLElement} el
260
+ */
261
+ function getContentRect(el) {
262
+ let rect = getRect(el);
263
+ const paddingLeft = parseInt(css(el, 'padding-left')),
264
+ paddingTop = parseInt(css(el, 'padding-top')),
265
+ paddingRight = parseInt(css(el, 'padding-right')),
266
+ paddingBottom = parseInt(css(el, 'padding-bottom'));
267
+ rect.top += paddingTop + parseInt(css(el, 'border-top-width'));
268
+ rect.left += paddingLeft + parseInt(css(el, 'border-left-width'));
269
+ // Client Width/Height includes padding only
270
+ rect.width = el.clientWidth - paddingLeft - paddingRight;
271
+ rect.height = el.clientHeight - paddingTop - paddingBottom;
272
+ rect.bottom = rect.top + rect.height;
273
+ rect.right = rect.left + rect.width;
274
+ return rect;
275
+ }
276
+
277
+ /**
278
+ * Checks if a side of an element is scrolled past a side of its parents
279
+ * @param {HTMLElement} el The element who's side being scrolled out of view is in question
280
+ * @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom')
281
+ * @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom')
282
+ * @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element
283
+ */
284
+ function isScrolledPast(el, elSide, parentSide) {
285
+ let parent = getParentAutoScrollElement(el, true),
286
+ elSideVal = getRect(el)[elSide];
287
+
288
+ /* jshint boss:true */
289
+ while (parent) {
290
+ let parentSideVal = getRect(parent)[parentSide],
291
+ visible;
292
+
293
+ if (parentSide === 'top' || parentSide === 'left') {
294
+ visible = elSideVal >= parentSideVal;
295
+ } else {
296
+ visible = elSideVal <= parentSideVal;
297
+ }
298
+
299
+ if (!visible) return parent;
300
+
301
+ if (parent === getWindowScrollingElement()) break;
302
+
303
+ parent = getParentAutoScrollElement(parent, false);
304
+ }
305
+
306
+ return false;
307
+ }
308
+
309
+
310
+
311
+ /**
312
+ * Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible)
313
+ * and non-draggable elements
314
+ * @param {HTMLElement} el The parent element
315
+ * @param {Number} childNum The index of the child
316
+ * @param {Object} options Parent Sortable's options
317
+ * @return {HTMLElement} The child at index childNum, or null if not found
318
+ */
319
+ function getChild(el, childNum, options, includeDragEl) {
320
+ let currentChild = 0,
321
+ i = 0,
322
+ children = el.children;
323
+
324
+ while (i < children.length) {
325
+ if (
326
+ children[i].style.display !== 'none' &&
327
+ children[i] !== Sortable.ghost &&
328
+ (includeDragEl || children[i] !== Sortable.dragged) &&
329
+ closest(children[i], options.draggable, el, false)
330
+ ) {
331
+ if (currentChild === childNum) {
332
+ return children[i];
333
+ }
334
+ currentChild++;
335
+ }
336
+
337
+ i++;
338
+ }
339
+ return null;
340
+ }
341
+
342
+ /**
343
+ * Gets the last child in the el, ignoring ghostEl or invisible elements (clones)
344
+ * @param {HTMLElement} el Parent element
345
+ * @param {selector} selector Any other elements that should be ignored
346
+ * @return {HTMLElement} The last child, ignoring ghostEl
347
+ */
348
+ function lastChild(el, selector) {
349
+ let last = el.lastElementChild;
350
+
351
+ while (
352
+ last &&
353
+ (
354
+ last === Sortable.ghost ||
355
+ css(last, 'display') === 'none' ||
356
+ selector && !matches(last, selector)
357
+ )
358
+ ) {
359
+ last = last.previousElementSibling;
360
+ }
361
+
362
+ return last || null;
363
+ }
364
+
365
+
366
+ /**
367
+ * Returns the index of an element within its parent for a selected set of
368
+ * elements
369
+ * @param {HTMLElement} el
370
+ * @param {selector} selector
371
+ * @return {number}
372
+ */
373
+ function index(el, selector) {
374
+ let index = 0;
375
+
376
+ if (!el || !el.parentNode) {
377
+ return -1;
378
+ }
379
+
380
+ /* jshint boss:true */
381
+ while (el = el.previousElementSibling) {
382
+ if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && el !== Sortable.clone && (!selector || matches(el, selector))) {
383
+ index++;
384
+ }
385
+ }
386
+
387
+ return index;
388
+ }
389
+
390
+ /**
391
+ * Returns the scroll offset of the given element, added with all the scroll offsets of parent elements.
392
+ * The value is returned in real pixels.
393
+ * @param {HTMLElement} el
394
+ * @return {Array} Offsets in the format of [left, top]
395
+ */
396
+ function getRelativeScrollOffset(el) {
397
+ let offsetLeft = 0,
398
+ offsetTop = 0,
399
+ winScroller = getWindowScrollingElement();
400
+
401
+ if (el) {
402
+ do {
403
+ let elMatrix = matrix(el),
404
+ scaleX = elMatrix.a,
405
+ scaleY = elMatrix.d;
406
+
407
+ offsetLeft += el.scrollLeft * scaleX;
408
+ offsetTop += el.scrollTop * scaleY;
409
+ } while (el !== winScroller && (el = el.parentNode));
410
+ }
411
+
412
+ return [offsetLeft, offsetTop];
413
+ }
414
+
415
+ /**
416
+ * Returns the index of the object within the given array
417
+ * @param {Array} arr Array that may or may not hold the object
418
+ * @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find
419
+ * @return {Number} The index of the object in the array, or -1
420
+ */
421
+ function indexOfObject(arr, obj) {
422
+ for (let i in arr) {
423
+ if (!arr.hasOwnProperty(i)) continue;
424
+ for (let key in obj) {
425
+ if (obj.hasOwnProperty(key) && obj[key] === arr[i][key]) return Number(i);
426
+ }
427
+ }
428
+ return -1;
429
+ }
430
+
431
+
432
+ function getParentAutoScrollElement(el, includeSelf) {
433
+ // skip to window
434
+ if (!el || !el.getBoundingClientRect) return getWindowScrollingElement();
435
+
436
+ let elem = el;
437
+ let gotSelf = false;
438
+ do {
439
+ // we don't need to get elem css if it isn't even overflowing in the first place (performance)
440
+ if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) {
441
+ let elemCSS = css(elem);
442
+ if (
443
+ elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') ||
444
+ elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')
445
+ ) {
446
+ if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement();
447
+
448
+ if (gotSelf || includeSelf) return elem;
449
+ gotSelf = true;
450
+ }
451
+ }
452
+ /* jshint boss:true */
453
+ } while (elem = elem.parentNode);
454
+
455
+ return getWindowScrollingElement();
456
+ }
457
+
458
+ function extend(dst, src) {
459
+ if (dst && src) {
460
+ for (let key in src) {
461
+ if (src.hasOwnProperty(key)) {
462
+ dst[key] = src[key];
463
+ }
464
+ }
465
+ }
466
+
467
+ return dst;
468
+ }
469
+
470
+
471
+ function isRectEqual(rect1, rect2) {
472
+ return Math.round(rect1.top) === Math.round(rect2.top) &&
473
+ Math.round(rect1.left) === Math.round(rect2.left) &&
474
+ Math.round(rect1.height) === Math.round(rect2.height) &&
475
+ Math.round(rect1.width) === Math.round(rect2.width);
476
+ }
477
+
478
+
479
+ let _throttleTimeout;
480
+ function throttle(callback, ms) {
481
+ return function () {
482
+ if (!_throttleTimeout) {
483
+ let args = arguments,
484
+ _this = this;
485
+
486
+ if (args.length === 1) {
487
+ callback.call(_this, args[0]);
488
+ } else {
489
+ callback.apply(_this, args);
490
+ }
491
+
492
+ _throttleTimeout = setTimeout(function () {
493
+ _throttleTimeout = void 0;
494
+ }, ms);
495
+ }
496
+ };
497
+ }
498
+
499
+
500
+ function cancelThrottle() {
501
+ clearTimeout(_throttleTimeout);
502
+ _throttleTimeout = void 0;
503
+ }
504
+
505
+
506
+ function scrollBy(el, x, y) {
507
+ el.scrollLeft += x;
508
+ el.scrollTop += y;
509
+ }
510
+
511
+
512
+ function clone(el) {
513
+ let Polymer = window.Polymer;
514
+ let $ = window.jQuery || window.Zepto;
515
+
516
+ if (Polymer && Polymer.dom) {
517
+ return Polymer.dom(el).cloneNode(true);
518
+ }
519
+ else if ($) {
520
+ return $(el).clone(true)[0];
521
+ }
522
+ else {
523
+ return el.cloneNode(true);
524
+ }
525
+ }
526
+
527
+
528
+ function setRect(el, rect) {
529
+ css(el, 'position', 'absolute');
530
+ css(el, 'top', rect.top);
531
+ css(el, 'left', rect.left);
532
+ css(el, 'width', rect.width);
533
+ css(el, 'height', rect.height);
534
+ }
535
+
536
+ function unsetRect(el) {
537
+ css(el, 'position', '');
538
+ css(el, 'top', '');
539
+ css(el, 'left', '');
540
+ css(el, 'width', '');
541
+ css(el, 'height', '');
542
+ }
543
+
544
+ function getChildContainingRectFromElement(container, options, ghostEl) {
545
+ const rect = {};
546
+
547
+ Array.from(container.children).forEach(child => {
548
+ if (!closest(child, options.draggable, container, false) || child.animated || child === ghostEl) return;
549
+ const childRect = getRect(child);
550
+ rect.left = Math.min(rect.left ?? Infinity, childRect.left);
551
+ rect.top = Math.min(rect.top ?? Infinity, childRect.top);
552
+ rect.right = Math.max(rect.right ?? -Infinity, childRect.right);
553
+ rect.bottom = Math.max(rect.bottom ?? -Infinity, childRect.bottom);
554
+ });
555
+ rect.width = rect.right - rect.left;
556
+ rect.height = rect.bottom - rect.top;
557
+ rect.x = rect.left;
558
+ rect.y = rect.top;
559
+ return rect;
560
+ }
561
+
562
+ const expando = 'Sortable' + (new Date).getTime();
563
+
564
+
565
+ export {
566
+ on,
567
+ off,
568
+ matches,
569
+ getParentOrHost,
570
+ closest,
571
+ toggleClass,
572
+ css,
573
+ matrix,
574
+ find,
575
+ getWindowScrollingElement,
576
+ getRect,
577
+ isScrolledPast,
578
+ getChild,
579
+ lastChild,
580
+ index,
581
+ getRelativeScrollOffset,
582
+ indexOfObject,
583
+ getParentAutoScrollElement,
584
+ extend,
585
+ isRectEqual,
586
+ throttle,
587
+ cancelThrottle,
588
+ scrollBy,
589
+ clone,
590
+ setRect,
591
+ unsetRect,
592
+ getContentRect,
593
+ getChildContainingRectFromElement,
594
+ expando
595
+ };
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_publishing_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 43.0.1
4
+ version: 43.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-27 00:00:00.000000000 Z
11
+ date: 2024-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: govuk_app_config
@@ -1856,6 +1856,12 @@ files:
1856
1856
  - node_modules/sortablejs/modular/sortable.core.esm.js
1857
1857
  - node_modules/sortablejs/modular/sortable.esm.js
1858
1858
  - node_modules/sortablejs/package.json
1859
+ - node_modules/sortablejs/src/Animation.js
1860
+ - node_modules/sortablejs/src/BrowserInfo.js
1861
+ - node_modules/sortablejs/src/EventDispatcher.js
1862
+ - node_modules/sortablejs/src/PluginManager.js
1863
+ - node_modules/sortablejs/src/Sortable.js
1864
+ - node_modules/sortablejs/src/utils.js
1859
1865
  homepage: https://github.com/alphagov/govuk_publishing_components
1860
1866
  licenses:
1861
1867
  - MIT