function parseRange(spec) {
  let [min, max] = [];
  const sepIndex = spec.indexOf('..');
  [min, max] = (~sepIndex ? [spec.slice(0, sepIndex), spec.slice(sepIndex + 2)] : [spec]).map(part => part.trim());
  let inclusive = !!max && max.startsWith('=');
  [min, max] = [min, inclusive ? (max ? max.slice(1) : min) : max].map(part => part || undefined);
  const strict = !~sepIndex;
  if (strict && !max) [max, inclusive] = [min, true];
  return {min, max, inclusive, strict};
}
Parse ranges in strings.
Syntax: `[a][..[=][b]]`
@param {string} spec
@example (valid) `a`, `a..`, `..b`, `a..b`, `a..=`, `..=b`, `a..=b`
@example (optional) ``, `..`, `..=`
@returns {{min: string; max: string; inclusive: boolean; strict: boolean;}}
- `min`: The minimum part of the range. E.g `5` in `5..10`
- `max`: The maximum part of the range. E.g `10` in `5..10`
- `inclusive`: Whether or not the maximum is a part of the range. E.g `true` in `5..=10`
- `strict`: Whether or not the spec was not a range. E.g `true` in `7`