Add js web stuff to landing page + documentation
This commit is contained in:
185
go/jsruntime/runtime/@solidjs/router/dist/utils.js
vendored
Normal file
185
go/jsruntime/runtime/@solidjs/router/dist/utils.js
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
import { createMemo, getOwner, runWithOwner } from "solid-js";
|
||||
const hasSchemeRegex = /^(?:[a-z0-9]+:)?\/\//i;
|
||||
const trimPathRegex = /^\/+|(\/)\/+$/g;
|
||||
export const mockBase = "http://sr";
|
||||
export function normalizePath(path, omitSlash = false) {
|
||||
const s = path.replace(trimPathRegex, "$1");
|
||||
return s ? (omitSlash || /^[?#]/.test(s) ? s : "/" + s) : "";
|
||||
}
|
||||
export function resolvePath(base, path, from) {
|
||||
if (hasSchemeRegex.test(path)) {
|
||||
return undefined;
|
||||
}
|
||||
const basePath = normalizePath(base);
|
||||
const fromPath = from && normalizePath(from);
|
||||
let result = "";
|
||||
if (!fromPath || path.startsWith("/")) {
|
||||
result = basePath;
|
||||
}
|
||||
else if (fromPath.toLowerCase().indexOf(basePath.toLowerCase()) !== 0) {
|
||||
result = basePath + fromPath;
|
||||
}
|
||||
else {
|
||||
result = fromPath;
|
||||
}
|
||||
return (result || "/") + normalizePath(path, !result);
|
||||
}
|
||||
export function invariant(value, message) {
|
||||
if (value == null) {
|
||||
throw new Error(message);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
export function joinPaths(from, to) {
|
||||
return normalizePath(from).replace(/\/*(\*.*)?$/g, "") + normalizePath(to);
|
||||
}
|
||||
export function extractSearchParams(url) {
|
||||
const params = {};
|
||||
url.searchParams.forEach((value, key) => {
|
||||
if (key in params) {
|
||||
if (Array.isArray(params[key]))
|
||||
params[key].push(value);
|
||||
else
|
||||
params[key] = [params[key], value];
|
||||
}
|
||||
else
|
||||
params[key] = value;
|
||||
});
|
||||
return params;
|
||||
}
|
||||
export function createMatcher(path, partial, matchFilters) {
|
||||
const [pattern, splat] = path.split("/*", 2);
|
||||
const segments = pattern.split("/").filter(Boolean);
|
||||
const len = segments.length;
|
||||
return (location) => {
|
||||
const locSegments = location.split("/").filter(Boolean);
|
||||
const lenDiff = locSegments.length - len;
|
||||
if (lenDiff < 0 || (lenDiff > 0 && splat === undefined && !partial)) {
|
||||
return null;
|
||||
}
|
||||
const match = {
|
||||
path: len ? "" : "/",
|
||||
params: {}
|
||||
};
|
||||
const matchFilter = (s) => matchFilters === undefined ? undefined : matchFilters[s];
|
||||
for (let i = 0; i < len; i++) {
|
||||
const segment = segments[i];
|
||||
const dynamic = segment[0] === ":";
|
||||
const locSegment = dynamic ? locSegments[i] : locSegments[i].toLowerCase();
|
||||
const key = dynamic ? segment.slice(1) : segment.toLowerCase();
|
||||
if (dynamic && matchSegment(locSegment, matchFilter(key))) {
|
||||
match.params[key] = locSegment;
|
||||
}
|
||||
else if (dynamic || !matchSegment(locSegment, key)) {
|
||||
return null;
|
||||
}
|
||||
match.path += `/${locSegment}`;
|
||||
}
|
||||
if (splat) {
|
||||
const remainder = lenDiff ? locSegments.slice(-lenDiff).join("/") : "";
|
||||
if (matchSegment(remainder, matchFilter(splat))) {
|
||||
match.params[splat] = remainder;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return match;
|
||||
};
|
||||
}
|
||||
function matchSegment(input, filter) {
|
||||
const isEqual = (s) => s === input;
|
||||
if (filter === undefined) {
|
||||
return true;
|
||||
}
|
||||
else if (typeof filter === "string") {
|
||||
return isEqual(filter);
|
||||
}
|
||||
else if (typeof filter === "function") {
|
||||
return filter(input);
|
||||
}
|
||||
else if (Array.isArray(filter)) {
|
||||
return filter.some(isEqual);
|
||||
}
|
||||
else if (filter instanceof RegExp) {
|
||||
return filter.test(input);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
export function scoreRoute(route) {
|
||||
const [pattern, splat] = route.pattern.split("/*", 2);
|
||||
const segments = pattern.split("/").filter(Boolean);
|
||||
return segments.reduce((score, segment) => score + (segment.startsWith(":") ? 2 : 3), segments.length - (splat === undefined ? 0 : 1));
|
||||
}
|
||||
export function createMemoObject(fn) {
|
||||
const map = new Map();
|
||||
const owner = getOwner();
|
||||
return new Proxy({}, {
|
||||
get(_, property) {
|
||||
if (!map.has(property)) {
|
||||
runWithOwner(owner, () => map.set(property, createMemo(() => fn()[property])));
|
||||
}
|
||||
return map.get(property)();
|
||||
},
|
||||
getOwnPropertyDescriptor() {
|
||||
return {
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
};
|
||||
},
|
||||
ownKeys() {
|
||||
return Reflect.ownKeys(fn());
|
||||
},
|
||||
has(_, property) {
|
||||
return property in fn();
|
||||
}
|
||||
});
|
||||
}
|
||||
export function mergeSearchString(search, params) {
|
||||
const merged = new URLSearchParams(search);
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
if (value == null || value === "" || (value instanceof Array && !value.length)) {
|
||||
merged.delete(key);
|
||||
}
|
||||
else {
|
||||
if (value instanceof Array) {
|
||||
// Delete all instances of the key before appending
|
||||
merged.delete(key);
|
||||
value.forEach(v => {
|
||||
merged.append(key, String(v));
|
||||
});
|
||||
}
|
||||
else {
|
||||
merged.set(key, String(value));
|
||||
}
|
||||
}
|
||||
});
|
||||
const s = merged.toString();
|
||||
return s ? `?${s}` : "";
|
||||
}
|
||||
export function expandOptionals(pattern) {
|
||||
let match = /(\/?\:[^\/]+)\?/.exec(pattern);
|
||||
if (!match)
|
||||
return [pattern];
|
||||
let prefix = pattern.slice(0, match.index);
|
||||
let suffix = pattern.slice(match.index + match[0].length);
|
||||
const prefixes = [prefix, (prefix += match[1])];
|
||||
// This section handles adjacent optional params. We don't actually want all permuations since
|
||||
// that will lead to equivalent routes which have the same number of params. For example
|
||||
// `/:a?/:b?/:c`? only has the unique expansion: `/`, `/:a`, `/:a/:b`, `/:a/:b/:c` and we can
|
||||
// discard `/:b`, `/:c`, `/:b/:c` by building them up in order and not recursing. This also helps
|
||||
// ensure predictability where earlier params have precidence.
|
||||
while ((match = /^(\/\:[^\/]+)\?/.exec(suffix))) {
|
||||
prefixes.push((prefix += match[1]));
|
||||
suffix = suffix.slice(match[0].length);
|
||||
}
|
||||
return expandOptionals(suffix).reduce((results, expansion) => [...results, ...prefixes.map(p => p + expansion)], []);
|
||||
}
|
||||
export function setFunctionName(obj, value) {
|
||||
Object.defineProperty(obj, "name", {
|
||||
value,
|
||||
writable: false,
|
||||
configurable: false
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
Reference in New Issue
Block a user