(() => {
const result = {
router_type: 'unknown',
path: location.pathname,
query: Object.fromEntries(new URLSearchParams(location.search)),
hash: location.hash.slice(1),
can_navigate: false,
details: null
};
if (window.__remixContext || window.__remixManifest) {
result.router_type = 'react-router';
result.can_navigate = true;
result.details = 'Remix';
return JSON.stringify(result);
}
if (window.__NEXT_DATA__ || window.next) {
result.router_type = 'nextjs';
result.can_navigate = !!(window.next?.router?.push);
const isAppRouter = !window.__NEXT_DATA__?.props;
result.details = isAppRouter ? 'App Router' : 'Pages Router';
return JSON.stringify(result);
}
const vueApp = document.querySelector('[data-v-app]')?.__vue_app__;
if (vueApp?.config?.globalProperties?.$router) {
result.router_type = 'vue-router';
result.can_navigate = true;
const router = vueApp.config.globalProperties.$router;
result.details = router.options?.history?.base ? 'Vue Router 4' : 'Vue Router';
return JSON.stringify(result);
}
if (window.Vue && document.querySelector('#app')?.__vue__?.$router) {
result.router_type = 'vue-router';
result.can_navigate = true;
result.details = 'Vue 2 Router';
return JSON.stringify(result);
}
if (window.ng || document.querySelector('[ng-version]')) {
result.router_type = 'angular-router';
result.can_navigate = true;
result.details = 'Angular (via History API)';
return JSON.stringify(result);
}
const reactRoot = document.querySelector('[data-reactroot], #root, #app');
if (reactRoot) {
const hasReactRouter = window.__REACT_DEVTOOLS_GLOBAL_HOOK__?.renderers?.size > 0;
if (hasReactRouter) {
result.router_type = 'react-router';
result.can_navigate = true;
result.details = 'React (via History API)';
return JSON.stringify(result);
}
}
if (location.protocol !== 'file:') {
result.router_type = 'history-api';
result.can_navigate = true;
result.details = 'Generic SPA (History API fallback)';
}
return JSON.stringify(result);
})()