1 | {"version":3,"file":"resolve-uri.umd.js","sources":["../src/resolve-uri.ts"],"sourcesContent":["type WhatWgUrl = import('url').URL;\ninterface Url extends WhatWgUrl {\n new (input: string, base?: string): WhatWgUrl;\n}\ndeclare var URL: unknown;\n\n/* istanbul ignore next */\nconst Url = (typeof URL !== 'undefined' ? URL : require('url').URL) as Url;\n\n// Matches \"..\", which must be preceeded by \"/\" or the start of the string, and\n// must be followed by a \"/\". We do not eat the following \"/\", so that the next\n// iteration can match on it.\nconst parentRegex = /(^|\\/)\\.\\.(?=\\/|$)/g;\n\nfunction isAbsoluteUrl(url: string): boolean {\n try {\n return !!new Url(url);\n } catch (e) {\n return false;\n }\n}\n\n/**\n * Creates a directory name that is guaranteed to not be in `str`.\n */\nfunction uniqInStr(str: string): string {\n let uniq = String(Math.random()).slice(2);\n while (str.indexOf(uniq) > -1) {\n /* istanbul ignore next */\n uniq += uniq;\n }\n return uniq;\n}\n\n/**\n * Removes the filename from the path (everything trailing the last \"/\"). This\n * is only safe to call on a path, never call with an absolute or protocol\n * relative URL.\n */\nfunction stripPathFilename(path: string): string {\n path = normalizePath(path);\n const index = path.lastIndexOf('/');\n return path.slice(0, index + 1);\n}\n\n/**\n * Normalizes a protocol-relative URL, but keeps it protocol relative by\n * stripping out the protocl before returning it.\n */\nfunction normalizeProtocolRelative(input: string, absoluteBase: string): string {\n const { href, protocol } = new Url(input, absoluteBase);\n return href.slice(protocol.length);\n}\n\n/**\n * Normalizes a simple path (one that has no \"..\"s, or is absolute so \"..\"s can\n * be normalized absolutely).\n */\nfunction normalizeSimplePath(input: string): string {\n const { href } = new Url(input, 'https://foo.com/');\n return href.slice('https://foo.com/'.length);\n}\n\n/**\n * Normalizes a path, ensuring that excess \"..\"s are preserved for relative\n * paths in the output.\n *\n * If the input is absolute, this will return an absolutey normalized path, but\n * it will not have a leading \"/\".\n *\n * If the input has a leading \"..\", the output will have a leading \"..\".\n *\n * If the input has a leading \".\", the output will not have a leading \".\"\n * unless there are too many \"..\"s, in which case there will be a leading \"..\".\n */\nfunction normalizePath(input: string): string {\n // If there are no \"..\"s, we can treat this as if it were an absolute path.\n // The return won't be an absolute path, so it's easy.\n if (!parentRegex.test(input)) return normalizeSimplePath(input);\n\n // We already found one \"..\". Let's see how many there are.\n let total = 1;\n while (parentRegex.test(input)) total++;\n\n // If there are \"..\"s, we need to prefix the the path with the same number of\n // unique directories. This is to ensure that we \"remember\" how many parent\n // directories we are accessing. Eg, \"../../..\" must keep 3, and \"foo/../..\"\n // must keep 1.\n const uniqDirectory = `z${uniqInStr(input)}/`;\n\n // uniqDirectory is just a \"z\", followed by numbers, followed by a \"/\". So\n // generating a runtime regex from it is safe. We'll use this search regex to\n // strip out our uniq directory names and insert any needed \"..\"s.\n const search = new RegExp(`^(?:${uniqDirectory})*`);\n\n // Now we can resolve the total path. If there are excess \"..\"s, they will\n // eliminate one or more of the unique directories we prefix with.\n const relative = normalizeSimplePath(uniqDirectory.repeat(total) + input);\n\n // We can now count the number of unique directories that were eliminated. If\n // there were 3, and 1 was eliminated, we know we only need to add 1 \"..\". If\n // 2 were eliminated, we need to insert 2 \"..\"s. If all 3 were eliminated,\n // then we need 3, etc. This replace is guranteed to match (it may match 0 or\n // more times), and we can count the total match to see how many were eliminated.\n return relative.replace(search, (all: string) => {\n const leftover = all.length / uniqDirectory.length;\n return '../'.repeat(total - leftover);\n });\n}\n\n/**\n * Attempts to resolve `input` URL relative to `base`.\n */\nexport default function resolve(input: string, base: string | undefined): string {\n if (!base) base = '';\n\n // Absolute URLs are very easy to resolve right.\n if (isAbsoluteUrl(input)) return new Url(input).href;\n\n if (base) {\n // Absolute URLs are easy...\n if (isAbsoluteUrl(base)) return new Url(input, base).href;\n\n // If base is protocol relative, we'll resolve with it but keep the result\n // protocol relative.\n if (base.startsWith('//')) return normalizeProtocolRelative(input, `https:${base}`);\n }\n\n // Normalize input, but keep it protocol relative. We know base doesn't supply\n // a protocol, because that would have been handled above.\n if (input.startsWith('//')) return normalizeProtocolRelative(input, 'https://foo.com/');\n\n // We now know that base (if there is one) and input are paths. We've handled\n // both absolute and protocol-relative variations above.\n\n // Absolute paths don't need any special handling, because they cannot have\n // extra \".\" or \"..\"s. That'll all be stripped away. Input takes priority here,\n // because if input is an absolute path, base path won't affect it in any way.\n if (input.startsWith('/')) return '/' + normalizeSimplePath(input);\n\n // Since input and base are paths, we need to join them to do any further\n // processing. Paths are joined at the directory level, so we need to remove\n // the base's filename before joining. We also know that input does not have a\n // leading slash, and that the stripped base will have a trailing slash if\n // there are any directories (or it'll be empty).\n const joined = stripPathFilename(base) + input;\n\n // If base is an absolute path, then input will be relative to it.\n if (base.startsWith('/')) return '/' + normalizeSimplePath(joined);\n\n // We now know both base (if there is one) and input are relative paths.\n const relative = normalizePath(joined);\n\n // If base started with a leading \".\", or there is no base and input started\n // with a \".\", then we need to ensure that the relative path starts with a\n // \".\". We don't know if relative starts with a \"..\", though, so check before\n // prepending.\n if ((base || input).startsWith('.') && !relative.startsWith('.')) {\n return './' + relative;\n }\n\n return relative;\n}\n"],"names":[],"mappings":"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"} |
---|