Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Requirements:
Consumers then install a pinned release:

```bash
npm install @aeei/docusaurus-theme@0.1.5
npm install @aeei/docusaurus-theme@0.1.7
```

This repository does not publish automatically from an unapproved working tree.
Expand Down
4 changes: 4 additions & 0 deletions examples/docs-starter/docs/guides/markdown-gfm.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ This page exercises standard Markdown, GFM, and Docusaurus docs conventions.

## Table of contents depth

### Inline code heading `provider-id`

This heading verifies that table-of-contents code uses the canonical inline code surface.

### Link targets

Jump to [paragraph flow](#paragraph-flow-and-emphasis), [lists](#lists-and-tasks), [tables](#tables), or [details](#details-and-admonitions).
Expand Down
4 changes: 2 additions & 2 deletions packages/docusaurus-theme/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@aeei/docusaurus-theme",
"version": "0.1.5",
"version": "0.1.7",
"description": "A shadcn Base Nova theme for Docusaurus docs.",
"license": "MIT",
"keywords": [
Expand All @@ -16,7 +16,7 @@
},
"repository": {
"type": "git",
"url": "https://github.com/aeei/docusaurus-theme.git",
"url": "git+https://github.com/aeei/docusaurus-theme.git",
"directory": "packages/docusaurus-theme"
},
"bugs": {
Expand Down
4 changes: 2 additions & 2 deletions packages/docusaurus-theme/src/package-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ it("uses the public docs-only package identity and metadata", () => {
const packageJson = JSON.parse(fs.readFileSync(packagePath, "utf8"));

expect(packageJson.name).toBe("@aeei/docusaurus-theme");
expect(packageJson.version).toBe("0.1.5");
expect(packageJson.version).toBe("0.1.7");
expect(packageJson.description).toBe(
"A shadcn Base Nova theme for Docusaurus docs."
);
expect(packageJson.repository).toEqual({
type: "git",
url: "https://github.com/aeei/docusaurus-theme.git",
url: "git+https://github.com/aeei/docusaurus-theme.git",
directory: "packages/docusaurus-theme",
});
expect(packageJson.bugs).toEqual({
Expand Down
12 changes: 8 additions & 4 deletions packages/docusaurus-theme/src/theme/Navbar/Content/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,12 @@ function NavbarNavigationMenuDocItem({
}: {
item: NavigationItemConfig;
}): ReactNode {
const { activeDoc } = useActiveDocContext(item.docsPluginId);
const doc = useLayoutDoc(item.docId!, item.docsPluginId);
const { docId, docsPluginId, label, ...navLinkProps } = item;
delete navLinkProps.type;
delete navLinkProps.items;

const { activeDoc } = useActiveDocContext(docsPluginId);
const doc = useLayoutDoc(docId!, docsPluginId);
const pageActive = activeDoc?.path === doc?.path;

if (doc === null || (doc.unlisted && !pageActive)) return null;
Expand All @@ -86,10 +90,10 @@ function NavbarNavigationMenuDocItem({
className={navigationMenuTriggerStyle()}
render={
<NavbarNavLink
{...item}
{...navLinkProps}
exact
to={doc.path}
label={item.label ?? doc.id}
label={label ?? doc.id}
isActive={() =>
pageActive ||
(!!activeDoc?.sidebar && activeDoc.sidebar === doc.sidebar)
Expand Down
6 changes: 5 additions & 1 deletion packages/docusaurus-theme/src/theme/TOCItems/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ function HeadingLabel({ html }: { html: string }): React.JSX.Element {
const code = part.match(codeContentPattern);
if (code) {
return (
<code key={index} dangerouslySetInnerHTML={{ __html: code[1] }} />
<code
key={index}
className="theme-code-inline"
dangerouslySetInnerHTML={{ __html: code[1] }}
/>
);
}

Expand Down
20 changes: 10 additions & 10 deletions packages/docusaurus-theme/src/theme/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
--theme-leading-sm: 1.25rem;
--theme-text-xs: 0.75rem;
--theme-leading-xs: 1rem;
--theme-prose-body-size: 0.9375rem;
--theme-prose-leading: 1.75;
--theme-backdrop-blur: 12px;
}

Expand Down Expand Up @@ -508,9 +510,9 @@ a[class*="skipToContent"]:focus {
--typeset-font-body: inherit;
--typeset-font-heading: var(--ifm-heading-font-family);
--typeset-font-mono: var(--ifm-font-family-monospace);
--typeset-size: 0.9375rem;
--typeset-size: var(--theme-prose-body-size);
--typeset-body-size: var(--typeset-size);
--typeset-leading: 1.75;
--typeset-leading: var(--theme-prose-leading);
--typeset-flow: 1.25em;
--typeset-muted: var(--muted-foreground);
--typeset-rule: var(--border);
Expand Down Expand Up @@ -1147,9 +1149,11 @@ a[class*="skipToContent"]:focus {
border-radius: min(calc(var(--radius) * 0.6), 0.35em);
background-color: var(--muted);
color: inherit;
font-family: var(--typeset-font-mono);
font-size: calc(var(--typeset-body-size) * 0.85);
line-height: var(--typeset-leading);
font-family: var(--typeset-font-mono, var(--ifm-font-family-monospace));
font-size: calc(
var(--typeset-body-size, var(--theme-prose-body-size)) * 0.85
);
line-height: var(--typeset-leading, var(--theme-prose-leading));
padding: 0.125em 0.3em;
}

Expand Down Expand Up @@ -1717,6 +1721,7 @@ a[class*="skipToContent"]:focus {
}

.theme-doc-markdown .docusaurus-mermaid-container {
margin-block-start: var(--typeset-flow);
display: flex;
justify-content: safe center;
overflow-x: auto;
Expand Down Expand Up @@ -1777,11 +1782,6 @@ a[class*="skipToContent"]:focus {
transition: color 150ms ease;
}

.table-of-contents__link code {
font-size: inherit;
line-height: inherit;
}

.table-of-contents__link[data-depth="3"] {
padding-left: calc(var(--spacing) * 4);
}
Expand Down
4 changes: 3 additions & 1 deletion packages/docusaurus-theme/src/theme/base.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ it("leaves component focus visuals to official primitives", () => {
});

it("keeps article prose size stable across responsive widths", () => {
expect(stylesheet).toContain("--typeset-size: 0.9375rem;");
expect(stylesheet).toContain("--theme-prose-body-size: 0.9375rem;");
expect(stylesheet).toContain("--theme-prose-leading: 1.75;");
expect(stylesheet).toContain("--typeset-size: var(--theme-prose-body-size);");
expect(stylesheet).toContain("--typeset-flow: 1.25em;");
expect(stylesheet).toContain("--typeset-body-size: var(--typeset-size);");
expect(stylesheet).toContain("font-size: var(--typeset-body-size);");
Expand Down
6 changes: 6 additions & 0 deletions packages/docusaurus-theme/src/theme/mermaid-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ describe("Mermaid ownership contract", () => {
);
});

it("keeps Mermaid diagrams in the article flow rhythm", () => {
expect(stylesheet).toMatch(
/\.theme-doc-markdown \.docusaurus-mermaid-container\s*\{[^}]*margin-block-start: var\(--typeset-flow\);[^}]*\}/
);
});

it("keeps wide actual-route diagrams readable in a horizontal scroll surface", () => {
expect(stylesheet).toMatch(
/\.docusaurus-mermaid-container\s*\{[\s\S]*justify-content: safe center;[\s\S]*overflow-x: auto;/
Expand Down
21 changes: 21 additions & 0 deletions packages/docusaurus-theme/src/theme/prose-contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,27 @@ describe("prose ownership contract", () => {
expect(stylesheet).not.toContain(":where(:not(pre) > code)");
});

it("reuses canonical inline code styling in table-of-contents labels", () => {
const tocTree = fs.readFileSync(
path.join(__dirname, "TOCItems/Tree.tsx"),
"utf8"
);

expect(tocTree).toContain('className="theme-code-inline"');
expect(stylesheet).not.toContain(".table-of-contents__link code {");
expect(stylesheet).toContain("--theme-prose-body-size: 0.9375rem;");
expect(stylesheet).toContain("--theme-prose-leading: 1.75;");
expect(stylesheet).toContain(
"var(--typeset-font-mono, var(--ifm-font-family-monospace))"
);
expect(stylesheet).toContain(
"var(--typeset-body-size, var(--theme-prose-body-size))"
);
expect(stylesheet).toContain(
"var(--typeset-leading, var(--theme-prose-leading))"
);
});

it("keeps heading hash links on the official inherit contract", () => {
expect(canonicalStylesheet).toContain(
canonicalize(`${localBoundary}:where(:is(h1, h2, h3, h4, h5, h6) :is(a))`)
Expand Down
10 changes: 4 additions & 6 deletions scripts/audit-critical-ui-relations.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,15 @@ async function openPage(browser, width, route = "showcase/mdx-playground") {
backgroundColor: navbarBlur.backgroundColor,
},
toc: {
headerOutsideScroll: Boolean(
tocHeader && tocScroll && !tocScroll.contains(tocHeader)
),
headerAbsent: !tocHeader,
scrollFade: fadeActive(tocScroll),
},
};
});
await page.evaluate(() => scrollTo(0, document.documentElement.scrollHeight));
await page.waitForTimeout(50);
const sidebarFooterBoundary = await page.evaluate(() => {
const sidebar = document.querySelector(".theme-doc-sidebar-container");
const sidebar = document.querySelector(".theme-doc-sidebar-desktop");
const sidebarFooter = sidebar?.querySelector(
'[data-slot="sidebar-footer"]'
);
Expand Down Expand Up @@ -335,10 +333,10 @@ async function openPage(browser, width, route = "showcase/mdx-playground") {
);
expect(
desktopSurface.sidebarScrollFade === true &&
desktopSurface.toc.headerOutsideScroll === true &&
desktopSurface.toc.headerAbsent === true &&
desktopSurface.toc.scrollFade === true &&
mobileSurface.sidebarScrollFade === true,
"LNB and TOC scroll viewports must use scroll-fade while the TOC header remains fixed",
"LNB and TOC scroll viewports must use scroll-fade without restoring the removed TOC header",
{ desktopSurface, mobileSurface }
);
expect(
Expand Down
25 changes: 13 additions & 12 deletions scripts/audit-docs-starter.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,15 @@ async function auditRoute(page, viewport, theme, route) {
});

const desktopSidebar = document.querySelector(
'[data-slot="sidebar-container"]'
".theme-doc-sidebar-desktop"
);
const mobileTrigger = document.querySelector(
"[data-mobile-navigation-trigger]"
);
const responsiveFailure =
viewportName === "desktop"
? !desktopSidebar ||
getComputedStyle(desktopSidebar).position !== "fixed" ||
getComputedStyle(desktopSidebar).position !== "sticky" ||
mobileTrigger?.getBoundingClientRect().width
: !!desktopSidebar?.getBoundingClientRect().width ||
!mobileTrigger?.getBoundingClientRect().width;
Expand Down Expand Up @@ -252,20 +252,21 @@ async function auditDesktopInteractions(page, theme) {
window.scrollTo(0, document.documentElement.scrollHeight)
);
await page.waitForTimeout(100);
const sidebarContainer = await visible(
page,
'[data-slot="sidebar-container"]'
);
const sidebarRect = await sidebarContainer.boundingBox();
const desktopSidebar = await visible(page, ".theme-doc-sidebar-desktop");
const sidebarRect = await desktopSidebar.boundingBox();
const sidebarFooter = await visible(page, '[data-slot="sidebar-footer"]');
const footerRect = await sidebarFooter.boundingBox();
const sidebarFooterRect = await sidebarFooter.boundingBox();
const pageFooter = await visible(page, ".theme-layout-footer");
const pageFooterRect = await pageFooter.boundingBox();
if (
!sidebarRect ||
!footerRect ||
sidebarRect.y < 40 ||
footerRect.y + footerRect.height > 901
!sidebarFooterRect ||
!pageFooterRect ||
sidebarRect.y < -1 ||
sidebarRect.y + sidebarRect.height > pageFooterRect.y + 1 ||
sidebarFooterRect.y + sidebarFooterRect.height > pageFooterRect.y + 1
) {
throw new Error("fixed Sidebar/footer scroll state failed");
throw new Error("sticky Sidebar/footer boundary failed");
}

const themeTrigger = page.getByRole("button", { name: /^Color theme:/ });
Expand Down
34 changes: 34 additions & 0 deletions tests/theme-parity.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,40 @@ test("inline code keeps one component-owned surface inside Details", async ({
}
});

test("table-of-contents code reuses the canonical inline code surface", async ({
page,
}) => {
await page.setViewportSize({ width: 1440, height: 900 });
await page.goto(markdownRoute);

const metrics = await page.evaluate(() => {
const content = Array.from(
document.querySelectorAll(".theme-doc-markdown h3 code")
).find((element) => element.textContent === "provider-id");
const toc = Array.from(
document.querySelectorAll(".table-of-contents__link code")
).find((element) => element.textContent === "provider-id");
const read = (element?: Element) => {
if (!element) return null;
const style = getComputedStyle(element);
return {
className: element.className,
fontFamily: style.fontFamily,
fontSize: style.fontSize,
lineHeight: style.lineHeight,
padding: style.padding,
borderRadius: style.borderRadius,
backgroundColor: style.backgroundColor,
};
};
return { content: read(content), toc: read(toc) };
});

expect(metrics.content).not.toBeNull();
expect(metrics.toc).toEqual(metrics.content);
expect(metrics.toc?.className).toContain("theme-code-inline");
});

test("CodeBlock matches the official shadcn docs surface", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 900 });
await page.goto(markdownRoute);
Expand Down