cloudflare/InstantPlugin
Publicmirrored fromhttps://github.com/cloudflare/InstantPlugin
app/lib/parse-url.js
67lines · modecode
unknown
| 1 | import {parse} from "url" |
| 2 | |
| 3 | const PARAM_PATTERN = /(\#|\?)/ |
| 4 | const PATH_DELIMITER_PATTERN = /[^\w+]/ |
| 5 | const PROTOCOL_PATTERN = /(^\S*:?)(\/\/)/ |
| 6 | const DEFAULT_PROTOCOL_MATCH = [null, "//", ""] |
| 7 | |
| 8 | const chunkIsPresent = chunk => chunk.value.length !== 0 |
| 9 | |
| 10 | export default function parseURL(string) { |
| 11 | const [urlWithPath, paramDelimiter = "", paramString = ""] = string.split(PARAM_PATTERN) || [] |
| 12 | |
| 13 | const parsed = parse(urlWithPath, false, true) |
| 14 | const {host, pathname} = parsed |
| 15 | const pathCharacters = pathname.split("") |
| 16 | let url |
| 17 | |
| 18 | if (parsed.protocol) { |
| 19 | url = [parsed.protocol, "//", host].join("") |
| 20 | } |
| 21 | else { |
| 22 | const [, protocol, delimiter] = urlWithPath.match(PROTOCOL_PATTERN) || DEFAULT_PROTOCOL_MATCH |
| 23 | |
| 24 | url = [protocol, delimiter, host].join("") |
| 25 | } |
| 26 | |
| 27 | const pathChunks = pathCharacters |
| 28 | .reduce((accumulator, character) => { |
| 29 | if (PATH_DELIMITER_PATTERN.test(character)) { |
| 30 | accumulator.push({type: "delimiter", value: character}, {type: "path", value: ""}) |
| 31 | } |
| 32 | else { |
| 33 | accumulator[accumulator.length - 1].value += character |
| 34 | } |
| 35 | |
| 36 | return accumulator |
| 37 | }, [{type: "path", value: ""}]) |
| 38 | .filter(chunkIsPresent) |
| 39 | |
| 40 | const paramChunks = [] |
| 41 | |
| 42 | paramString.split("&").forEach((param, index, paramArray) => { |
| 43 | const [key, value] = param.split("=") |
| 44 | |
| 45 | paramChunks.push( |
| 46 | {type: "param-group", value: [ |
| 47 | {type: "param-key", value: key}, |
| 48 | {type: "delimiter", value: "="}, |
| 49 | {type: "param-value", value} |
| 50 | ]} |
| 51 | ) |
| 52 | |
| 53 | if (index !== paramArray.length - 1) { |
| 54 | paramChunks.push({type: "delimiter", value: "&"}) |
| 55 | } |
| 56 | }) |
| 57 | |
| 58 | if (paramChunks.length) { |
| 59 | paramChunks.unshift({type: "delimiter", value: paramDelimiter}) |
| 60 | } |
| 61 | |
| 62 | return [ |
| 63 | {type: "url", value: url}, |
| 64 | ...pathChunks, |
| 65 | ...paramChunks |
| 66 | ] |
| 67 | } |