mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:00:42 +00:00
fix: Found one regression in the exported transcript mobile sidebar tr (#74584)
Co-authored-by: openclaw-clawsweeper[bot] <280122609+openclaw-clawsweeper[bot]@users.noreply.github.com> Co-authored-by: Val Alexander <68980965+BunsDev@users.noreply.github.com>
This commit is contained in:
@@ -1063,7 +1063,7 @@ body {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#hamburger {
|
||||
#hamburger.sidebar-menu-trigger {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import vm from "node:vm";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import vm from "node:vm";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
type SessionEntry = {
|
||||
@@ -141,6 +141,32 @@ function now() {
|
||||
return new Date("2026-02-24T00:00:00.000Z").toISOString();
|
||||
}
|
||||
|
||||
function selectorSpecificity(selector: string): [number, number, number] {
|
||||
const ids = selector.match(/#[\w-]+/g)?.length ?? 0;
|
||||
const classes = selector.match(/\.[\w-]+/g)?.length ?? 0;
|
||||
const withoutIdsOrClasses = selector.replace(/#[\w-]+|\.[\w-]+/g, " ");
|
||||
const elements = withoutIdsOrClasses
|
||||
.split(/[\s>+~]+/)
|
||||
.filter((part) => /^[a-z][\w-]*$/i.test(part)).length;
|
||||
return [ids, classes, elements];
|
||||
}
|
||||
|
||||
function compareSpecificity(left: [number, number, number], right: [number, number, number]) {
|
||||
for (let index = 0; index < left.length; index += 1) {
|
||||
if (left[index] !== right[index]) {
|
||||
return left[index] - right[index];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function firstSelectorForDisplay(css: string, display: string, startAt: number): string | null {
|
||||
const displayRule = new RegExp(`([^{}]+)\\{[^{}]*\\bdisplay\\s*:\\s*${display}\\s*;`, "g");
|
||||
displayRule.lastIndex = startAt;
|
||||
const match = displayRule.exec(css);
|
||||
return match?.[1]?.split(",").at(-1)?.trim() ?? null;
|
||||
}
|
||||
|
||||
describe("export html sidebar trigger affordance", () => {
|
||||
it("keeps the hamburger sidebar trigger accessible and visibly interactive", () => {
|
||||
expect(templateHtml).toContain('id="hamburger" class="sidebar-menu-trigger"');
|
||||
@@ -154,6 +180,21 @@ describe("export html sidebar trigger affordance", () => {
|
||||
expect(templateCss).toContain("background: var(--container-bg);");
|
||||
expect(templateCss).toContain("#hamburger.sidebar-menu-trigger:focus-visible {");
|
||||
});
|
||||
|
||||
it("lets the mobile hamburger display rule win the CSS cascade", () => {
|
||||
const baseSelector = "#hamburger.sidebar-menu-trigger";
|
||||
const mobileMediaIndex = templateCss.indexOf("@media (max-width: 900px)");
|
||||
const mobileSelector = firstSelectorForDisplay(templateCss, "inline-flex", mobileMediaIndex);
|
||||
|
||||
expect(mobileMediaIndex).toBeGreaterThan(templateCss.indexOf(`${baseSelector} {`));
|
||||
expect(mobileSelector).toBe(baseSelector);
|
||||
if (!mobileSelector) {
|
||||
throw new Error("Missing mobile hamburger display rule");
|
||||
}
|
||||
expect(
|
||||
compareSpecificity(selectorSpecificity(mobileSelector), selectorSpecificity(baseSelector)),
|
||||
).toBeGreaterThanOrEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("export html security hardening", () => {
|
||||
|
||||
Reference in New Issue
Block a user