github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/web/src/PathBuilder.tsx (about) 1 import React, { useContext } from "react" 2 3 // A little helper class for building paths relative to the root of the app. 4 class PathBuilder { 5 private protocol: string 6 private host: string 7 private snapId: string = "" 8 9 static forTesting(host: string, pathname: string) { 10 return new PathBuilder({ 11 protocol: "http:", 12 host: host, 13 pathname: pathname, 14 }) 15 } 16 17 constructor(loc: { protocol: string; host: string; pathname: string }) { 18 this.host = loc.host 19 this.protocol = loc.protocol 20 21 const snapshotRe = new RegExp("^/snapshot/([^/]+)") 22 let snapMatch = snapshotRe.exec(loc.pathname) 23 if (snapMatch) { 24 this.snapId = snapMatch[1] 25 } 26 } 27 28 getDataUrl() { 29 if (this.isSnapshot()) { 30 return this.snapshotDataUrl() 31 } 32 return this.isSecure() 33 ? `wss://${this.host}/ws/view` 34 : `ws://${this.host}/ws/view` 35 } 36 37 isSecure(): boolean { 38 return this.protocol === "https:" 39 } 40 41 isSnapshot(): boolean { 42 return this.snapId !== "" 43 } 44 45 private snapshotDataUrl(): string { 46 return `/api/snapshot/${this.snapId}` 47 } 48 49 private snapshotPathBase(): string { 50 return `/snapshot/${this.snapId}` 51 } 52 53 rootPath() { 54 if (this.isSnapshot()) { 55 return this.snapshotPathBase() 56 } 57 return "" 58 } 59 60 path(relPath: string): string { 61 if (relPath[0] !== "/") { 62 throw new Error('relPath should start with "/", actual:' + relPath) 63 } 64 return this.rootPath() + relPath 65 } 66 67 // A template literal function for encoding paths. 68 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals 69 encpath(strings: TemplateStringsArray, ...values: string[]): string { 70 let result = [strings[0]] 71 for (let i = 0; i < values.length; i++) { 72 result.push(encodeURIComponent(values[i]), strings[i + 1]) 73 } 74 return this.path(result.join("")) 75 } 76 } 77 78 export default PathBuilder 79 80 const pathBuilderContext = React.createContext<PathBuilder>( 81 new PathBuilder(window.location) 82 ) 83 84 export function usePathBuilder(): PathBuilder { 85 return useContext(pathBuilderContext) 86 } 87 export const PathBuilderProvider = pathBuilderContext.Provider