code-server-2/src/common/util.ts

100 lines
2.7 KiB
TypeScript
Raw Normal View History

2020-03-16 17:43:32 +00:00
import { logger, field } from "@coder/logger"
2020-02-04 19:27:46 +00:00
export interface Options {
base: string
2020-07-29 20:02:14 +00:00
csStaticBase: string
2020-02-05 23:30:09 +00:00
logLevel: number
2020-02-04 19:27:46 +00:00
}
2019-10-28 19:03:13 +00:00
/**
* Split a string up to the delimiter. If the delimiter doesn't exist the first
* item will have all the text and the second item will be an empty string.
*/
export const split = (str: string, delimiter: string): [string, string] => {
2020-02-04 19:27:46 +00:00
const index = str.indexOf(delimiter)
return index !== -1 ? [str.substring(0, index).trim(), str.substring(index + 1)] : [str, ""]
}
export const plural = (count: number): string => (count === 1 ? "" : "s")
export const generateUuid = (length = 24): string => {
const possible = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
return Array(length)
.fill(1)
.map(() => possible[Math.floor(Math.random() * possible.length)])
.join("")
}
/**
* Remove extra slashes in a URL.
*/
export const normalize = (url: string, keepTrailing = false): string => {
return url.replace(/\/\/+/g, "/").replace(/\/+$/, keepTrailing ? "/" : "")
}
/**
* Remove leading and trailing slashes.
*/
export const trimSlashes = (url: string): string => {
return url.replace(/^\/+|\/+$/g, "")
}
2020-07-29 20:02:14 +00:00
/**
* Resolve a relative base against the window location. This is used for
* anything that doesn't work with a relative path.
*/
export const resolveBase = (base?: string): string => {
// After resolving the base will either start with / or be an empty string.
if (!base || base.startsWith("/")) {
return base || ""
}
const parts = location.pathname.replace(/^\//g, "").split("/")
parts[parts.length - 1] = base
const url = new URL(location.origin + "/" + parts.join("/"))
return normalize(url.pathname)
}
2020-02-04 19:27:46 +00:00
/**
2020-03-16 17:43:32 +00:00
* Get options embedded in the HTML or query params.
2020-02-04 19:27:46 +00:00
*/
export const getOptions = <T extends Options>(): T => {
2020-03-16 17:43:32 +00:00
let options: T
2020-02-04 19:27:46 +00:00
try {
2020-07-29 20:02:14 +00:00
options = JSON.parse(document.getElementById("coder-options")!.getAttribute("data-settings")!)
2020-03-16 17:43:32 +00:00
} catch (error) {
options = {} as T
}
const params = new URLSearchParams(location.search)
const queryOpts = params.get("options")
if (queryOpts) {
options = {
...options,
2020-03-16 17:43:32 +00:00
...JSON.parse(queryOpts),
}
2020-02-04 19:27:46 +00:00
}
2020-03-16 17:43:32 +00:00
2020-07-29 20:02:14 +00:00
logger.level = options.logLevel
options.base = resolveBase(options.base)
options.csStaticBase = resolveBase(options.csStaticBase)
2020-03-16 17:43:32 +00:00
logger.debug("got options", field("options", options))
return options
2020-02-04 19:27:46 +00:00
}
/**
* Wrap the value in an array if it's not already an array. If the value is
* undefined return an empty array.
*/
export const arrayify = <T>(value?: T | T[]): T[] => {
if (Array.isArray(value)) {
return value
}
if (typeof value === "undefined") {
return []
}
return [value]
}