fix: support direct help route
This commit is contained in:
@@ -468,7 +468,7 @@ async function serveCloudWeb() {
|
||||
}
|
||||
|
||||
const routePath = url.pathname.replace(/\/+$/, "") || "/";
|
||||
const relativePath = routePath === "/" || routePath === "/gate" || routePath === "/diagnostics/gate" ? "index.html" : url.pathname.slice(1);
|
||||
const relativePath = routePath === "/" || routePath === "/gate" || routePath === "/diagnostics/gate" || routePath === "/help" ? "index.html" : url.pathname.slice(1);
|
||||
for (const root of roots) {
|
||||
const candidate = path.resolve(root, relativePath);
|
||||
if (!candidate.startsWith(root)) continue;
|
||||
|
||||
@@ -64,6 +64,7 @@ const diagnosticsRequiredTerms = Object.freeze([
|
||||
]);
|
||||
|
||||
const gateRouteAliases = Object.freeze(["/gate", "/diagnostics/gate"]);
|
||||
const helpRouteAliases = Object.freeze(["/help"]);
|
||||
|
||||
const incompletePrimaryNavLabels = Object.freeze(["台", "证", "诊", "帮"]);
|
||||
|
||||
@@ -253,6 +254,11 @@ function runStaticSmoke() {
|
||||
evidence: gateRouteAliases
|
||||
});
|
||||
|
||||
addCheck(checks, blockers, "direct-help-route-alias", helpRouteAliasesAreServed(files.app, artifactPublisher, buildScript, distContractScript), "/help is a direct user-facing help alias and does not become the default route.", {
|
||||
blocker: "runtime_blocker",
|
||||
evidence: [...helpRouteAliases, "routeFromLocation final fallback is workspace"]
|
||||
});
|
||||
|
||||
addCheck(checks, blockers, "feedback-120-wiring-table", wiringTableContract(files.html), "Patch-panel wiring panel is a table with source, target, status, evidence source, and trace/evidence columns.", {
|
||||
blocker: "contract_blocker",
|
||||
evidence: requiredWiringColumns
|
||||
@@ -966,6 +972,19 @@ function gateRouteAliasesAreServed(app, artifactPublisher, buildScript, distCont
|
||||
);
|
||||
}
|
||||
|
||||
function helpRouteAliasesAreServed(app, artifactPublisher, buildScript, distContractScript) {
|
||||
const routeBody = functionBody(app, "routeFromLocation");
|
||||
return (
|
||||
/helpPathnames\(\)\.has/u.test(routeBody) &&
|
||||
helpRouteAliases.every((route) => app.includes(`"${route}"`)) &&
|
||||
helpRouteAliases.every((route) => artifactPublisher.includes(`routePath === "${route}"`)) &&
|
||||
/buildCloudWebDist/u.test(buildScript) &&
|
||||
/help\/index\.html/u.test(distContractScript) &&
|
||||
/return "help"/u.test(routeBody) &&
|
||||
finalRouteFallback(app) === "workspace"
|
||||
);
|
||||
}
|
||||
|
||||
function wiringTableContract(html) {
|
||||
const wiringPanel = html.match(/<section\b[^>]*\bdata-side-panel=["']wiring["'][\s\S]*?<\/section>/u)?.[0] ?? "";
|
||||
return requiredWiringColumns.every((column) => wiringPanel.includes(`<th>${column}</th>`));
|
||||
@@ -1321,7 +1340,7 @@ function inspectHelpRoute(html, app) {
|
||||
/data-route=["']help["']/u.test(html) ||
|
||||
/data-view=["']help["']/u.test(html) ||
|
||||
/#help\b/u.test(html + app) ||
|
||||
/pathname[\s\S]{0,160}\/help/u.test(app);
|
||||
/pathname[\s\S]{0,220}\/help/u.test(app);
|
||||
const finalFallback = finalRouteFallback(app);
|
||||
const helpViewHidden = helpViewTag ? /\bhidden\b/u.test(helpViewTag) : false;
|
||||
return {
|
||||
@@ -1983,6 +2002,12 @@ export async function runDevCloudWorkbenchMobileSmoke() {
|
||||
await page.click('[data-route="help"]');
|
||||
await page.waitForFunction(() => document.querySelector("#help-content")?.dataset.helpState === "ready", null, { timeout: 8000 });
|
||||
const help = await inspectHelpMarkdownRoute(page);
|
||||
await page.goto(new URL("/#/help", server.url).toString(), { waitUntil: "networkidle", timeout: 15000 });
|
||||
await page.waitForFunction(() => document.querySelector("#help-content")?.dataset.helpState === "ready", null, { timeout: 8000 });
|
||||
const slashHashHelp = await inspectHelpMarkdownRoute(page);
|
||||
await page.goto(new URL("/help", server.url).toString(), { waitUntil: "networkidle", timeout: 15000 });
|
||||
await page.waitForFunction(() => document.querySelector("#help-content")?.dataset.helpState === "ready", null, { timeout: 8000 });
|
||||
const directHelp = await inspectHelpMarkdownRoute(page);
|
||||
await page.click('[data-route="workspace"]');
|
||||
await page.waitForFunction(() => document.querySelector('[data-view="workspace"]')?.hidden === false, null, { timeout: 8000 });
|
||||
await page.click("#explorer-toggle");
|
||||
@@ -2018,10 +2043,22 @@ export async function runDevCloudWorkbenchMobileSmoke() {
|
||||
},
|
||||
{
|
||||
id: "mobile-help-markdown-route",
|
||||
status: help.nonDefaultMarkdownHelp && help.termsPresent ? "pass" : "blocked",
|
||||
summary: "Help opens as a non-default internal route rendered from help.md by the vendored Markdown renderer.",
|
||||
status: help.nonDefaultMarkdownHelp && help.routeIsHashHelp && help.termsPresent ? "pass" : "blocked",
|
||||
summary: "Help opens from the rail as a non-default hash route rendered from help.md by the vendored Markdown renderer.",
|
||||
observations: help
|
||||
},
|
||||
{
|
||||
id: "mobile-slash-hash-help-route",
|
||||
status: slashHashHelp.nonDefaultMarkdownHelp && slashHashHelp.routeIsSlashHashHelp && slashHashHelp.termsPresent ? "pass" : "blocked",
|
||||
summary: "Direct #/help opens the user-facing help view.",
|
||||
observations: slashHashHelp
|
||||
},
|
||||
{
|
||||
id: "mobile-direct-help-route",
|
||||
status: directHelp.nonDefaultMarkdownHelp && directHelp.routeIsDirectHelp && directHelp.termsPresent ? "pass" : "blocked",
|
||||
summary: "Direct /help opens the user-facing help view instead of raw API 404 JSON.",
|
||||
observations: directHelp
|
||||
},
|
||||
{
|
||||
id: "mobile-default-hit-test",
|
||||
status: closed.primaryControlsReachable ? "pass" : "blocked",
|
||||
@@ -2109,7 +2146,7 @@ async function startStaticWebServer(options = {}) {
|
||||
return;
|
||||
}
|
||||
let pathname = decodeURIComponent(url.pathname);
|
||||
if (pathname === "/" || pathname === "/workbench" || pathname === "/gate" || pathname === "/diagnostics/gate") {
|
||||
if (pathname === "/" || pathname === "/workbench" || pathname === "/gate" || pathname === "/diagnostics/gate" || pathname === "/help") {
|
||||
pathname = "/index.html";
|
||||
}
|
||||
const filePath = path.resolve(webRoot, pathname.replace(/^\/+/, ""));
|
||||
@@ -2490,6 +2527,7 @@ async function inspectHelpMarkdownRoute(page) {
|
||||
document.body.scrollHeight <= document.body.clientHeight + 2;
|
||||
return {
|
||||
hash: window.location.hash,
|
||||
pathname: window.location.pathname,
|
||||
helpState: helpContent?.dataset.helpState ?? null,
|
||||
workspaceHidden: workspace ? workspace.hidden : null,
|
||||
gateHidden: gate ? gate.hidden : null,
|
||||
@@ -2504,8 +2542,11 @@ async function inspectHelpMarkdownRoute(page) {
|
||||
helpPanelScrolls: Boolean(helpScroll && helpScroll.scrollHeight > helpScroll.clientHeight && helpScroll.after > helpScroll.before),
|
||||
rootStillLocked,
|
||||
helpScroll,
|
||||
routeIsHashHelp: window.location.hash === "#help",
|
||||
routeIsSlashHashHelp: window.location.hash === "#/help",
|
||||
routeIsDirectHelp: (window.location.pathname.replace(/\/+$/, "") || "/") === "/help",
|
||||
nonDefaultMarkdownHelp:
|
||||
window.location.hash === "#help" &&
|
||||
(window.location.hash === "#help" || window.location.hash === "#/help" || (window.location.pathname.replace(/\/+$/, "") || "/") === "/help") &&
|
||||
workspace?.hidden === true &&
|
||||
gate?.hidden === true &&
|
||||
help?.hidden === false &&
|
||||
|
||||
Reference in New Issue
Block a user