Google Maps URL parser

by Arjan Haverkamp

JavaScript

const GmapUrlParser = (() => {

const extractWaypoints = (urlStr) => {
  const url = new URL(urlStr);
  const waypoints = [];

  // Helper: parse "lat,lng" into numbers
  const parsePair = s => {
    const m = s.match(/^\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*$/);
    return m ? { lat: parseFloat(m[1]), lng: parseFloat(m[2]) } : null;
  };

  // 1) Handle /maps/dir/... path style
  // e.g. /maps/dir/66.31986,14.17176/63.147366,21.197411/62.91022,27.6866/@64.239886,10.447078,5z
  if (url.pathname.includes('/maps/dir/')) {
    // take everything after /maps/dir/ and before any '@' segment
    const after = decodeURIComponent(url.pathname.split('/maps/dir/')[1] || '');
    const trimmed = after.split('/@')[0]; // drop viewport part if present
    const segments = trimmed.split('/').filter(Boolean);

    for (const seg of segments) {
      const p = parsePair(seg);
      if (p) waypoints.push(p);
    }
  }

  // 2) Handle api=1 style with query params
  // e.g. .../dir/?api=1&origin=lat,lng&destination=lat,lng&waypoints=lat1,lng1|lat2,lng2
  if (url.searchParams.get('api') === '1') {
    const tryPush = value => {
      if (!value) return;
      const p = parsePair(decodeURIComponent(value));
      if (p) waypoints.push(p);
    };

    tryPush(url.searchParams.get('origin'));
    const wps = url.searchParams.get('waypoints');
    if (wps) {
      for (const part of decodeURIComponent(wps).split('|')) {
        tryPush(part);
      }
    }
    tryPush(url.searchParams.get('destination'));
  }

  return waypoints;
}

const getRouteOptions = (urlStr) => {
  let avoidHighways = false;
  let avoidTolls = false;
  let avoidFerries = false;
  let travelMode = 'driving';

  if (/data=([^\?&$]+)/.test(urlStr)) {
    const data = RegExp.$1;

    if (data.indexOf('!3e1') != -1) {
      travelMode = 'bicycling';
    }
    else if (data.indexOf('!3e2') != -1) {
      travelMode = 'walking';
    }
    else if...