fix(web): cover deep document headings
This commit is contained in:
@@ -25,7 +25,7 @@ const paragraphs = Array.from(
|
|||||||
const bodyMd =
|
const bodyMd =
|
||||||
`# Workspace Memory\n\nThis document is read-only.\n\n| Very wide heading | Another heading | Decision |\n| --- | --- | --- |\n| ${
|
`# Workspace Memory\n\nThis document is read-only.\n\n| Very wide heading | Another heading | Decision |\n| --- | --- | --- |\n| ${
|
||||||
"wide-value-".repeat(16)
|
"wide-value-".repeat(16)
|
||||||
} | stable | keep scrolling local |\n\n\`\`\`rust\nfn example() { println!("${
|
} | stable | keep scrolling local |\n\n##### Deep document heading\n\n###### Deepest document heading\n\n\`\`\`rust\nfn example() { println!("${
|
||||||
"wide-code-".repeat(18)
|
"wide-code-".repeat(18)
|
||||||
}"); }\n\`\`\`\n\n[Safe link](https://example.com) [Unsafe link](javascript:alert(1))\n\n<img src=x onerror=alert(1)>\n\n${paragraphs}\n\n## T-661 UNIQUE END MARKER`;
|
}"); }\n\`\`\`\n\n[Safe link](https://example.com) [Unsafe link](javascript:alert(1))\n\n<img src=x onerror=alert(1)>\n\n${paragraphs}\n\n## T-661 UNIQUE END MARKER`;
|
||||||
|
|
||||||
|
|||||||
@@ -165,6 +165,21 @@ Deno.test("production Memory shell renders safe Markdown and scrolls to its end
|
|||||||
);
|
);
|
||||||
assertEquals(await page.locator("blockquote").count() > 0, true);
|
assertEquals(await page.locator("blockquote").count() > 0, true);
|
||||||
assertEquals(await page.locator("ul li").count() > 0, true);
|
assertEquals(await page.locator("ul li").count() > 0, true);
|
||||||
|
for (
|
||||||
|
const heading of [
|
||||||
|
{ selector: "h5", text: "Deep document heading" },
|
||||||
|
{ selector: "h6", text: "Deepest document heading" },
|
||||||
|
]
|
||||||
|
) {
|
||||||
|
const element = page.locator(heading.selector, { hasText: heading.text });
|
||||||
|
assertEquals(await element.count(), 1);
|
||||||
|
assert(
|
||||||
|
await element.evaluate((node) =>
|
||||||
|
Number.parseFloat((globalThis as any).getComputedStyle(node).fontSize) >= 12
|
||||||
|
),
|
||||||
|
`${heading.selector} fell below the design language minimum text size`,
|
||||||
|
);
|
||||||
|
}
|
||||||
assertEquals(await page.locator('a[href="https://example.com"]').count(), 1);
|
assertEquals(await page.locator('a[href="https://example.com"]').count(), 1);
|
||||||
assertEquals(await page.locator('a[href^="javascript:"]').count(), 0);
|
assertEquals(await page.locator('a[href^="javascript:"]').count(), 0);
|
||||||
assertEquals(await page.locator("article img, article script").count(), 0);
|
assertEquals(await page.locator("article img, article script").count(), 0);
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ test("renders document Markdown semantics through the shared safe policy", async
|
|||||||
const source = [
|
const source = [
|
||||||
"# Memory heading",
|
"# Memory heading",
|
||||||
"",
|
"",
|
||||||
|
"##### Deep heading",
|
||||||
|
"",
|
||||||
|
"###### Deepest heading",
|
||||||
|
"",
|
||||||
"A paragraph with **strong context** and `inline-code`.",
|
"A paragraph with **strong context** and `inline-code`.",
|
||||||
"",
|
"",
|
||||||
"- first item",
|
"- first item",
|
||||||
@@ -36,10 +40,15 @@ test("renders document Markdown semantics through the shared safe policy", async
|
|||||||
expect(container.querySelector("table")).not.toBeNull();
|
expect(container.querySelector("table")).not.toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expect(container.querySelector("h5")?.textContent).toBe("Deep heading");
|
||||||
|
expect(container.querySelector("h6")?.textContent).toBe("Deepest heading");
|
||||||
expect(container.querySelector("strong")?.textContent).toBe("strong context");
|
expect(container.querySelector("strong")?.textContent).toBe("strong context");
|
||||||
expect(container.querySelectorAll("li")).toHaveLength(2);
|
expect(container.querySelectorAll("li")).toHaveLength(2);
|
||||||
expect(container.querySelector("blockquote")?.textContent).toContain("durable quote");
|
expect(container.querySelector("blockquote")?.textContent).toContain(
|
||||||
expect(container.querySelector('a[href="https://example.com"]')).not.toBeNull();
|
"durable quote",
|
||||||
|
);
|
||||||
|
expect(container.querySelector('a[href="https://example.com"]')).not
|
||||||
|
.toBeNull();
|
||||||
expect(container.querySelectorAll("a")).toHaveLength(1);
|
expect(container.querySelectorAll("a")).toHaveLength(1);
|
||||||
expect(container.querySelector("img")).toBeNull();
|
expect(container.querySelector("img")).toBeNull();
|
||||||
expect(container.querySelector("script")).toBeNull();
|
expect(container.querySelector("script")).toBeNull();
|
||||||
@@ -52,13 +61,16 @@ test("renders document Markdown semantics through the shared safe policy", async
|
|||||||
);
|
);
|
||||||
expect(tableRegion?.tabIndex).toBe(0);
|
expect(tableRegion?.tabIndex).toBe(0);
|
||||||
expect(codeRegion?.tabIndex).toBe(0);
|
expect(codeRegion?.tabIndex).toBe(0);
|
||||||
expect(codeRegion?.querySelector("pre > code")?.textContent).toContain("println!");
|
expect(codeRegion?.querySelector("pre > code")?.textContent).toContain(
|
||||||
|
"println!",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("wraps long prose and identifiers without turning them into document-level controls", async () => {
|
test("wraps long prose and identifiers without turning them into document-level controls", async () => {
|
||||||
const longIdentifier = "memory-identifier-".repeat(40);
|
const longIdentifier = "memory-identifier-".repeat(40);
|
||||||
const { container } = render(DocumentMarkdown, {
|
const { container } = render(DocumentMarkdown, {
|
||||||
text: `Long value: ${longIdentifier}\n\n<details open><summary>unsafe HTML</summary></details>`,
|
text:
|
||||||
|
`Long value: ${longIdentifier}\n\n<details open><summary>unsafe HTML</summary></details>`,
|
||||||
});
|
});
|
||||||
|
|
||||||
await waitFor(() => expect(container.textContent).toContain(longIdentifier));
|
await waitFor(() => expect(container.textContent).toContain(longIdentifier));
|
||||||
|
|||||||
@@ -41,7 +41,9 @@
|
|||||||
|
|
||||||
:global(.document-markdown h2),
|
:global(.document-markdown h2),
|
||||||
:global(.document-markdown h3),
|
:global(.document-markdown h3),
|
||||||
:global(.document-markdown h4) {
|
:global(.document-markdown h4),
|
||||||
|
:global(.document-markdown h5),
|
||||||
|
:global(.document-markdown h6) {
|
||||||
margin: var(--space-6) 0 var(--space-2);
|
margin: var(--space-6) 0 var(--space-2);
|
||||||
color: var(--text-strong);
|
color: var(--text-strong);
|
||||||
font-size: var(--font-size-body);
|
font-size: var(--font-size-body);
|
||||||
@@ -53,7 +55,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
:global(.document-markdown h3),
|
:global(.document-markdown h3),
|
||||||
:global(.document-markdown h4) {
|
:global(.document-markdown h4),
|
||||||
|
:global(.document-markdown h5),
|
||||||
|
:global(.document-markdown h6) {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user