From fe8e8dbd7242d750f2004f4bb7d10bf63e352315 Mon Sep 17 00:00:00 2001 From: Jiapeng Ji Date: Wed, 12 Nov 2025 14:55:23 -0800 Subject: [PATCH] Fix documentation pages redirect to github.io issues fix url schema check issue Add proper console err for catch error blocks --- _layouts/default.html | 13 ++- assets/js/nav.js | 236 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 239 insertions(+), 10 deletions(-) diff --git a/_layouts/default.html b/_layouts/default.html index 7e1ec98..4b87d0a 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -4,8 +4,17 @@ + {{ page.title }} - + @@ -23,7 +32,7 @@
{% for item in section.items %} - + {{ item.title }} diff --git a/assets/js/nav.js b/assets/js/nav.js index a84a93e..a3e0e66 100644 --- a/assets/js/nav.js +++ b/assets/js/nav.js @@ -47,6 +47,42 @@ }); // Ensure search results stay on developers.procore.com under /documentation var basePath = "/documentation"; + + // Function to rewrite search result links for iframe display + function rewriteSearchResultLinks() { + if (window.self !== window.top) { + try { + var parentOrigin = window.location.ancestorOrigins && window.location.ancestorOrigins.length > 0 + ? window.location.ancestorOrigins[0] + : document.referrer ? new URL(document.referrer).origin : null; + + if (parentOrigin) { + $("#results-container a").each(function() { + var $link = $(this); + var originalHref = $link.attr("href"); + + // Skip if already processed or special links + if ($link.data("original-href") || !originalHref || originalHref.startsWith("#") || originalHref.startsWith("mailto:") || originalHref.startsWith("javascript:") || originalHref.startsWith("data:") || originalHref.startsWith("vbscript:")) { + return; + } + + // Get the path from the href + var path = originalHref; + if (!path.startsWith("/")) { + path = "/" + path; + } + + // Store original and set to parent origin for hover display + $link.data("original-href", originalHref); + $link.attr("href", parentOrigin + path); + }); + } + } catch (err) { + console.warn("Could not rewrite search result links:", err); + } + } + } + var sjs = SimpleJekyllSearch({ searchInput: document.getElementById("search-input"), resultsContainer: document.getElementById("results-container"), @@ -65,32 +101,216 @@ return path + (u.search || "") + (u.hash || ""); } catch (e) { // Fallback for odd values (e.g., "page.html" or "#anchor") + console.error("Error parsing URL in templateMiddleware:", e, "value:", value); if (value.charAt(0) === "#") return value; return basePath.replace(/\/$/, "") + "/" + value.replace(/^\//, ""); } } return value; }, + noResultsText: "No results found", + limit: 10, + fuzzy: false }); - // Defensive: if a result link is absolute and points off-site, rewrite it to this host + + // Use MutationObserver to rewrite search result links when they're added + if (window.self !== window.top) { + var resultsContainer = document.getElementById("results-container"); + if (resultsContainer) { + var observer = new MutationObserver(function(mutations) { + rewriteSearchResultLinks(); + }); + observer.observe(resultsContainer, { + childList: true, + subtree: true + }); + } + } + // Handle clicks on search result links - navigate within iframe if in one $("#results-container").on("click", "a", function (e) { - var href = $(this).attr("href"); - if (!href) return; - // Only act on absolute URLs - if (/^https?:\/\//i.test(href)) { + var $link = $(this); + var currentHref = $link.attr("href"); + var originalHref = $link.data("original-href"); + + if (!currentHref) return; + + // If in iframe and link points to parent origin, navigate within iframe + if (window.self !== window.top) { + try { + var parentOrigin = window.location.ancestorOrigins && window.location.ancestorOrigins.length > 0 + ? window.location.ancestorOrigins[0] + : document.referrer ? new URL(document.referrer).origin : null; + + if (parentOrigin && currentHref.startsWith(parentOrigin)) { + e.preventDefault(); + var path = new URL(currentHref).pathname + new URL(currentHref).search + new URL(currentHref).hash; + // Update iframe location + window.location.href = path; + // Update parent window URL via postMessage (cross-origin safe) + try { + window.parent.postMessage({ + type: 'documentationNavigation', + path: path, + fullUrl: parentOrigin + path + }, parentOrigin); + } catch (e) { + console.warn("Could not send navigation message to parent:", e); + } + return false; + } + } catch (err) { + console.error("Error handling search result link click:", err); + } + } + + // Fallback: handle absolute URLs pointing off-site + if (/^https?:\/\//i.test(currentHref)) { try { - var u = new URL(href); + var u = new URL(currentHref); if (u.origin !== window.location.origin) { e.preventDefault(); var path = u.pathname; if (!path.startsWith(basePath)) { path = basePath.replace(/\/$/, "") + "/" + path.replace(/^\//, ""); } - window.location.href = path + (u.search || "") + (u.hash || ""); + var newUrl = path + (u.search || "") + (u.hash || ""); + window.location.href = newUrl; + return false; } } catch (err) { - // ignore malformed URLs + console.error("Error handling absolute URL in search result click:", err, "href:", currentHref); } } }); + + // If in an iframe, rewrite link hrefs for hover display but intercept clicks to navigate within iframe + if (window.self !== window.top) { + try { + var parentOrigin = window.location.ancestorOrigins && window.location.ancestorOrigins.length > 0 + ? window.location.ancestorOrigins[0] + : document.referrer ? new URL(document.referrer).origin : null; + + if (parentOrigin) { + // Function to get the actual path from a href + function getPathFromHref(href) { + if (!href || href.startsWith("#") || href.startsWith("mailto:") || href.startsWith("javascript:") || href.startsWith("data:") || href.startsWith("vbscript:")) { + return null; + } + try { + if (href.match(/^https?:\/\//)) { + return new URL(href).pathname + new URL(href).search + new URL(href).hash; + } else { + // Relative URL + return href.startsWith("/") ? href : "/" + href; + } + } catch (e) { + console.error("Error parsing href in getPathFromHref:", e, "href:", href); + return href.startsWith("/") ? href : "/" + href; + } + } + + // Rewrite navigation links for hover display + $("nav a").each(function() { + var $link = $(this); + var originalHref = $link.attr("href"); + var path = getPathFromHref(originalHref); + + if (path && !path.startsWith("#") && !path.startsWith("mailto:") && !path.startsWith("javascript:") && !path.startsWith("data:") && !path.startsWith("vbscript:")) { + // Store original href in data attribute + $link.data("original-href", originalHref); + // Set href to parent origin for hover display + $link.attr("href", parentOrigin + path); + } + }); + + // Rewrite links in main content area for hover display + $("main a").each(function() { + var $link = $(this); + var originalHref = $link.attr("href"); + var path = getPathFromHref(originalHref); + + if (path && !path.startsWith("#") && !path.startsWith("mailto:") && !path.startsWith("javascript:") && !path.startsWith("data:") && !path.startsWith("vbscript:")) { + // Store original href in data attribute + $link.data("original-href", originalHref); + // Set href to parent origin for hover display + $link.attr("href", parentOrigin + path); + } + }); + + // Intercept clicks on navigation and content links to navigate within iframe + $(document).on("click", "nav a, main a", function(e) { + var $link = $(this); + var originalHref = $link.data("original-href"); + var currentHref = $link.attr("href"); + + // If we have a stored original href, use it; otherwise check current href + var hrefToUse = originalHref || currentHref; + + // Skip external links, anchors, and special protocols + if (!hrefToUse || hrefToUse.startsWith("#") || hrefToUse.startsWith("mailto:") || hrefToUse.startsWith("javascript:") || hrefToUse.startsWith("data:") || hrefToUse.startsWith("vbscript:")) { + return; // Let default behavior handle these + } + + // If current href points to parent origin (for display), navigate using the path within iframe + if (currentHref && currentHref.startsWith(parentOrigin)) { + e.preventDefault(); + var path = new URL(currentHref).pathname + new URL(currentHref).search + new URL(currentHref).hash; + // Update iframe location + window.location.href = path; + // Update parent window URL via postMessage (cross-origin safe) + try { + window.parent.postMessage({ + type: 'documentationNavigation', + path: path, + fullUrl: parentOrigin + path + }, parentOrigin); + } catch (e) { + console.warn("Could not send navigation message to parent:", e); + } + return false; + } else if (hrefToUse.match(/^https?:\/\//) && !hrefToUse.startsWith(window.location.origin) && !hrefToUse.startsWith(parentOrigin)) { + // External link (not parent origin, not current origin) - let it open normally + return; + } else if (originalHref && originalHref.startsWith(parentOrigin)) { + // Original href was parent origin - navigate within iframe + e.preventDefault(); + var path = new URL(originalHref).pathname + new URL(originalHref).search + new URL(originalHref).hash; + // Update iframe location + window.location.href = path; + // Update parent window URL via postMessage (cross-origin safe) + try { + window.parent.postMessage({ + type: 'documentationNavigation', + path: path, + fullUrl: parentOrigin + path + }, parentOrigin); + } catch (e) { + console.warn("Could not send navigation message to parent:", e); + } + return false; + } else if (hrefToUse && !hrefToUse.match(/^https?:\/\//)) { + // Relative link - navigate within iframe and update parent URL + e.preventDefault(); + var path = hrefToUse.startsWith("/") ? hrefToUse : "/" + hrefToUse; + // Update iframe location + window.location.href = path; + // Update parent window URL via postMessage (cross-origin safe) + try { + window.parent.postMessage({ + type: 'documentationNavigation', + path: path, + fullUrl: parentOrigin + path + }, parentOrigin); + } catch (e) { + console.warn("Could not send navigation message to parent:", e); + } + return false; + } + // For other cases, let default behavior work + }); + } + } catch (err) { + console.warn("Could not rewrite links for parent origin:", err); + } + } })();