Index: node_modules/ip-address/src/v6/constants.ts
===================================================================
--- node_modules/ip-address/src/v6/constants.ts	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/ip-address/src/v6/constants.ts	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,79 @@
+export const BITS = 128;
+export const GROUPS = 8;
+
+/**
+ * Represents IPv6 address scopes
+ * @memberof Address6
+ * @static
+ */
+export const SCOPES: { [key: number]: string | undefined } = {
+  0: 'Reserved',
+  1: 'Interface local',
+  2: 'Link local',
+  4: 'Admin local',
+  5: 'Site local',
+  8: 'Organization local',
+  14: 'Global',
+  15: 'Reserved',
+} as const;
+
+/**
+ * Represents IPv6 address types
+ * @memberof Address6
+ * @static
+ */
+export const TYPES: { [key: string]: string | undefined } = {
+  'ff01::1/128': 'Multicast (All nodes on this interface)',
+  'ff01::2/128': 'Multicast (All routers on this interface)',
+  'ff02::1/128': 'Multicast (All nodes on this link)',
+  'ff02::2/128': 'Multicast (All routers on this link)',
+  'ff05::2/128': 'Multicast (All routers in this site)',
+  'ff02::5/128': 'Multicast (OSPFv3 AllSPF routers)',
+  'ff02::6/128': 'Multicast (OSPFv3 AllDR routers)',
+  'ff02::9/128': 'Multicast (RIP routers)',
+  'ff02::a/128': 'Multicast (EIGRP routers)',
+  'ff02::d/128': 'Multicast (PIM routers)',
+  'ff02::16/128': 'Multicast (MLDv2 reports)',
+  'ff01::fb/128': 'Multicast (mDNSv6)',
+  'ff02::fb/128': 'Multicast (mDNSv6)',
+  'ff05::fb/128': 'Multicast (mDNSv6)',
+  'ff02::1:2/128': 'Multicast (All DHCP servers and relay agents on this link)',
+  'ff05::1:2/128': 'Multicast (All DHCP servers and relay agents in this site)',
+  'ff02::1:3/128': 'Multicast (All DHCP servers on this link)',
+  'ff05::1:3/128': 'Multicast (All DHCP servers in this site)',
+  '::/128': 'Unspecified',
+  '::1/128': 'Loopback',
+  'ff00::/8': 'Multicast',
+  'fe80::/10': 'Link-local unicast',
+} as const;
+
+/**
+ * A regular expression that matches bad characters in an IPv6 address
+ * @memberof Address6
+ * @static
+ */
+export const RE_BAD_CHARACTERS = /([^0-9a-f:/%])/gi;
+
+/**
+ * A regular expression that matches an incorrect IPv6 address
+ * @memberof Address6
+ * @static
+ */
+export const RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\/$)/gi;
+
+/**
+ * A regular expression that matches an IPv6 subnet
+ * @memberof Address6
+ * @static
+ */
+export const RE_SUBNET_STRING = /\/\d{1,3}(?=%|$)/;
+
+/**
+ * A regular expression that matches an IPv6 zone
+ * @memberof Address6
+ * @static
+ */
+export const RE_ZONE_STRING = /%.*$/;
+
+export const RE_URL = /^\[{0,1}([0-9a-f:]+)\]{0,1}/;
+export const RE_URL_WITH_PORT = /\[([0-9a-f:]+)\]:([0-9]{1,5})/;
Index: node_modules/ip-address/src/v6/helpers.ts
===================================================================
--- node_modules/ip-address/src/v6/helpers.ts	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/ip-address/src/v6/helpers.ts	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,48 @@
+/**
+ * @returns {String} the string with all zeroes contained in a <span>
+ */
+export function spanAllZeroes(s: string): string {
+  return s.replace(/(0+)/g, '<span class="zero">$1</span>');
+}
+
+/**
+ * @returns {String} the string with each character contained in a <span>
+ */
+export function spanAll(s: string, offset: number = 0): string {
+  const letters = s.split('');
+
+  return letters
+    .map(
+      (n, i) => `<span class="digit value-${n} position-${i + offset}">${spanAllZeroes(n)}</span>`,
+    )
+    .join('');
+}
+
+function spanLeadingZeroesSimple(group: string): string {
+  return group.replace(/^(0+)/, '<span class="zero">$1</span>');
+}
+
+/**
+ * @returns {String} the string with leading zeroes contained in a <span>
+ */
+export function spanLeadingZeroes(address: string): string {
+  const groups = address.split(':');
+
+  return groups.map((g) => spanLeadingZeroesSimple(g)).join(':');
+}
+
+/**
+ * Groups an address
+ * @returns {String} a grouped address
+ */
+export function simpleGroup(addressString: string, offset: number = 0): string[] {
+  const groups = addressString.split(':');
+
+  return groups.map((g, i) => {
+    if (/group-v4/.test(g)) {
+      return g;
+    }
+
+    return `<span class="hover-group group-${i + offset}">${spanLeadingZeroesSimple(g)}</span>`;
+  });
+}
Index: node_modules/ip-address/src/v6/regular-expressions.ts
===================================================================
--- node_modules/ip-address/src/v6/regular-expressions.ts	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
+++ node_modules/ip-address/src/v6/regular-expressions.ts	(revision 81bc7da776d8cda42939ef4ab350c88d13b4941f)
@@ -0,0 +1,94 @@
+import * as v6 from './constants';
+
+export function groupPossibilities(possibilities: string[]): string {
+  return `(${possibilities.join('|')})`;
+}
+
+export function padGroup(group: string): string {
+  if (group.length < 4) {
+    return `0{0,${4 - group.length}}${group}`;
+  }
+
+  return group;
+}
+
+export const ADDRESS_BOUNDARY = '[^A-Fa-f0-9:]';
+
+export function simpleRegularExpression(groups: string[]) {
+  const zeroIndexes: number[] = [];
+
+  groups.forEach((group, i) => {
+    const groupInteger = parseInt(group, 16);
+
+    if (groupInteger === 0) {
+      zeroIndexes.push(i);
+    }
+  });
+
+  // You can technically elide a single 0, this creates the regular expressions
+  // to match that eventuality
+  const possibilities = zeroIndexes.map((zeroIndex) =>
+    groups
+      .map((group, i) => {
+        if (i === zeroIndex) {
+          const elision = i === 0 || i === v6.GROUPS - 1 ? ':' : '';
+
+          return groupPossibilities([padGroup(group), elision]);
+        }
+
+        return padGroup(group);
+      })
+      .join(':'),
+  );
+
+  // The simplest case
+  possibilities.push(groups.map(padGroup).join(':'));
+
+  return groupPossibilities(possibilities);
+}
+
+export function possibleElisions(
+  elidedGroups: number,
+  moreLeft?: boolean,
+  moreRight?: boolean,
+): string {
+  const left = moreLeft ? '' : ':';
+  const right = moreRight ? '' : ':';
+
+  const possibilities = [];
+
+  // 1. elision of everything (::)
+  if (!moreLeft && !moreRight) {
+    possibilities.push('::');
+  }
+
+  // 2. complete elision of the middle
+  if (moreLeft && moreRight) {
+    possibilities.push('');
+  }
+
+  if ((moreRight && !moreLeft) || (!moreRight && moreLeft)) {
+    // 3. complete elision of one side
+    possibilities.push(':');
+  }
+
+  // 4. elision from the left side
+  possibilities.push(`${left}(:0{1,4}){1,${elidedGroups - 1}}`);
+
+  // 5. elision from the right side
+  possibilities.push(`(0{1,4}:){1,${elidedGroups - 1}}${right}`);
+
+  // 6. no elision
+  possibilities.push(`(0{1,4}:){${elidedGroups - 1}}0{1,4}`);
+
+  // 7. elision (including sloppy elision) from the middle
+  for (let groups = 1; groups < elidedGroups - 1; groups++) {
+    for (let position = 1; position < elidedGroups - groups; position++) {
+      possibilities.push(
+        `(0{1,4}:){${position}}:(0{1,4}:){${elidedGroups - position - groups - 1}}0{1,4}`,
+      );
+    }
+  }
+
+  return groupPossibilities(possibilities);
+}
