| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| (function () { |
| if (typeof window === "undefined" || typeof document === "undefined") return; |
| if (window.__bifrostBaseUrlSwitcherLoaded) return; |
| window.__bifrostBaseUrlSwitcherLoaded = true; |
|
|
| var DEFAULT_URL = "http://localhost:8080"; |
| var STORAGE_KEY = "bifrost_base_url"; |
| |
| |
| var snapshots = new WeakMap(); |
|
|
| function readStoredUrl() { |
| try { |
| var v = window.localStorage.getItem(STORAGE_KEY); |
| return v && v.trim() ? v.trim() : DEFAULT_URL; |
| } catch (e) { |
| return DEFAULT_URL; |
| } |
| } |
|
|
| function writeStoredUrl(url) { |
| try { |
| window.localStorage.setItem(STORAGE_KEY, url); |
| } catch (e) { |
| |
| } |
| } |
|
|
| function normalizeUrl(input) { |
| if (!input) return DEFAULT_URL; |
| var url = String(input).trim(); |
| if (!url) return DEFAULT_URL; |
| if (!/^https?:\/\//i.test(url)) url = "http://" + url; |
| return url.replace(/\/+$/, ""); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| function snapshotTextNodes(el) { |
| var walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null); |
| var entries = []; |
| var hasMatch = false; |
| var node; |
| while ((node = walker.nextNode())) { |
| var text = node.nodeValue || ""; |
| if (text.indexOf("localhost:8080") !== -1) hasMatch = true; |
| entries.push({ node: node, original: text }); |
| } |
| return hasMatch ? entries : null; |
| } |
|
|
| |
| |
| |
| |
| |
| function rewriteCodeBlocks(currentUrl) { |
| var blocks = document.querySelectorAll("pre code, code"); |
| var bareUrl = currentUrl.replace(/^https?:\/\//, ""); |
| for (var i = 0; i < blocks.length; i++) { |
| var el = blocks[i]; |
| var entries = snapshots.get(el); |
| if (entries === undefined) { |
| entries = snapshotTextNodes(el); |
| |
| |
| snapshots.set(el, entries); |
| } |
| if (!entries) continue; |
| for (var j = 0; j < entries.length; j++) { |
| var entry = entries[j]; |
| var next; |
| if (currentUrl === DEFAULT_URL) { |
| next = entry.original; |
| } else { |
| next = entry.original |
| .replace(/https?:\/\/localhost:8080/g, currentUrl) |
| .replace(/localhost:8080/g, bareUrl); |
| } |
| if (entry.node.nodeValue !== next) entry.node.nodeValue = next; |
| } |
| } |
| } |
|
|
| |
|
|
| |
| |
| |
| |
| |
| function findPlaygroundUrlInputs() { |
| var el = document.getElementById("api-playground-input"); |
| if (!el || el.__bifrostPlaygroundBound) return []; |
| return [el]; |
| } |
|
|
| function setNativeValue(el, value) { |
| |
| |
| var proto = Object.getPrototypeOf(el); |
| var descriptor = Object.getOwnPropertyDescriptor(proto, "value"); |
| if (descriptor && descriptor.set) descriptor.set.call(el, value); |
| else el.value = value; |
| el.dispatchEvent(new Event("input", { bubbles: true })); |
| el.dispatchEvent(new Event("change", { bubbles: true })); |
| } |
|
|
| function syncPlaygroundInputs(state) { |
| var inputs = findPlaygroundUrlInputs(); |
| for (var i = 0; i < inputs.length; i++) { |
| var el = inputs[i]; |
| if (el.__bifrostPlaygroundBound) continue; |
| el.__bifrostPlaygroundBound = true; |
|
|
| |
| |
| el.addEventListener("change", function (e) { |
| var v = normalizeUrl(e.target.value); |
| state.currentUrl = v; |
| writeStoredUrl(v); |
| rewriteCodeBlocks(v); |
| }); |
|
|
| |
| |
| |
| if (state.currentUrl !== DEFAULT_URL && el.value !== state.currentUrl) { |
| setNativeValue(el, state.currentUrl); |
| } |
| } |
| } |
|
|
| |
|
|
| function boot() { |
| var state = { currentUrl: normalizeUrl(readStoredUrl()) }; |
| rewriteCodeBlocks(state.currentUrl); |
| syncPlaygroundInputs(state); |
|
|
| |
| var pending = false; |
| var observer = new MutationObserver(function () { |
| if (pending) return; |
| pending = true; |
| window.requestAnimationFrame(function () { |
| pending = false; |
| rewriteCodeBlocks(state.currentUrl); |
| syncPlaygroundInputs(state); |
| }); |
| }); |
| observer.observe(document.body, { childList: true, subtree: true }); |
| } |
|
|
| if (document.readyState === "loading") { |
| document.addEventListener("DOMContentLoaded", boot); |
| } else { |
| boot(); |
| } |
| })(); |
|
|