Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tweak: toc with heading & styles #573

Merged
merged 13 commits into from
Jan 10, 2025
Merged
56 changes: 26 additions & 30 deletions gatsby/create-types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CreatePagesArgs } from 'gatsby'
import { generateConfig } from './path'
import { mdxAstToToc } from './toc'
import { Root, List } from 'mdast'
import { CreatePagesArgs } from "gatsby";
import { generateConfig } from "./path";
import { mdxAstToToc } from "./toc";
import { Root, List } from "mdast";

export const createExtraType = ({ actions }: CreatePagesArgs) => {
const { createTypes, createFieldExtension } = actions
const { createTypes, createFieldExtension } = actions;

const typeDefs = `
"""
Expand All @@ -26,12 +26,12 @@ export const createExtraType = ({ actions }: CreatePagesArgs) => {
hide_commit: Boolean
hide_leftNav: Boolean
}
`
`;

createTypes(typeDefs)
createTypes(typeDefs);

createFieldExtension({
name: 'navigation',
name: "navigation",
extend() {
return {
async resolve(
Expand All @@ -40,38 +40,34 @@ export const createExtraType = ({ actions }: CreatePagesArgs) => {
context: unknown,
info: any
) {
if (mdxNode.nav) return mdxNode.nav
const types = info.schema.getType('Mdx').getFields()
const slug = await types['slug'].resolve(mdxNode, args, context, {
fieldName: 'slug',
})
if (mdxNode.nav) return mdxNode.nav;
const types = info.schema.getType("Mdx").getFields();
const slug = await types["slug"].resolve(mdxNode, args, context, {
fieldName: "slug",
});

const mdxAST: Root = await types['mdxAST'].resolve(
const mdxAST: Root = await types["mdxAST"].resolve(
mdxNode,
args,
context,
{
fieldName: 'mdxAST',
fieldName: "mdxAST",
}
)
);

if (!slug.endsWith('TOC'))
throw new Error(`unsupported query in ${slug}`)
const { config } = generateConfig(slug)
const res = mdxAstToToc(
(mdxAST.children.find(node => node.type === 'list') as List)
.children,
config
)
mdxNode.nav = res
return res
if (!slug.endsWith("TOC"))
throw new Error(`unsupported query in ${slug}`);
const { config } = generateConfig(slug);
const res = mdxAstToToc(mdxAST.children, config);
mdxNode.nav = res;
return res;
},
}
};
},
})
});
createTypes(`
type Mdx implements Node {
navigation: JSON! @navigation
}
`)
}
`);
};
64 changes: 57 additions & 7 deletions gatsby/toc.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,86 @@
import { ListItem, List, Link, Paragraph, Text } from "mdast";
import {
ListItem,
List,
Link,
Paragraph,
Text,
Content,
PhrasingContent,
Heading,
} from "mdast";

import { RepoNav, RepoNavLink, PathConfig } from "../src/shared/interface";
import { generateUrl } from "./path";

export function mdxAstToToc(
ast: ListItem[],
ast: Content[],
config: PathConfig,
prefixId = `0`
): RepoNav {
return ast
.filter(
(node) =>
node.type === "list" || (node.type === "heading" && node.depth > 1)
)
.map((node, idx) => {
if (node.type === "list") {
return handleList(node.children, config, `${prefixId}-${idx}`);
} else {
return handleHeading((node as Heading).children, `${prefixId}-${idx}`);
}
})
.flat();
}

function handleList(ast: ListItem[], config: PathConfig, prefixId = `0`) {
return ast.map((node, idx) => {
const content = node.children as [Paragraph, List | undefined];
if (content.length > 0 && content.length <= 2) {
const ret = getContentFromLink(content[0], config);
const ret = getContentFromLink(content[0], config, `${prefixId}-${idx}`);

if (content[1]) {
const list = content[1];
if (list.type !== "list") {
throw new Error(`incorrect listitem in TOC.md`);
}

ret.children = mdxAstToToc(list.children, config, `${prefixId}-${idx}`);
ret.children = handleList(list.children, config, `${prefixId}-${idx}`);
}

ret.id = `${prefixId}-${idx}`;

return ret;
}

throw new Error(`incorrect format in TOC.md`);
});
}

function handleHeading(ast: PhrasingContent[], id = `0`): RepoNavLink[] {
const child = ast[0] as Text;
return [
{
type: "heading",
content: [child.value],
id,
},
];
}

function getContentFromLink(
content: Paragraph,
config: PathConfig
config: PathConfig,
id: string
): RepoNavLink {
if (content.type !== "paragraph" || content.children.length === 0) {
throw new Error(`incorrect format in TOC.md`);
}

const child = content.children[0] as Link | Text;
// use `image` as tag
const image = content.children.find((n) => n.type === "image");
const tag = image && {
value: image.alt!,
query: `?${image.url.split("?")[1]}`,
};

if (child.type === "link") {
if (child.children.length === 0) {
Expand All @@ -59,21 +100,30 @@ function getContentFromLink(

if (child.url.startsWith("https://")) {
return {
type: "nav",
link: child.url,
content,
tag,
id,
};
}

const urlSegs = child.url.split("/");
const filename = urlSegs[urlSegs.length - 1].replace(".md", "");

return {
type: "nav",
link: generateUrl(filename, config),
content,
tag,
id,
};
} else {
return {
type: "nav",
content: [child.value],
tag,
id,
};
}
}
5 changes: 4 additions & 1 deletion src/components/Layout/Seo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,13 @@ export default function Seo({
...meta,
]}
link={[
{
rel: "icon",
href: favicon.publicURL,
},
{
rel: "shortcut icon",
href: favicon.publicURL,
type: "image/x-icon",
},
...link,
]}
Expand Down
11 changes: 6 additions & 5 deletions src/components/Navigation/LeftNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Divider from "@mui/material/Divider";
import IconButton from "@mui/material/IconButton";
import MenuIcon from "@mui/icons-material/Menu";

import { DocLeftNav, PathConfig, BuildType } from "shared/interface";
import { RepoNav, PathConfig, BuildType } from "shared/interface";
import LinkComponent from "components/Link";
import LeftNavTree from "components/Navigation/LeftNavTree";
import VersionSelect, {
Expand All @@ -18,7 +18,7 @@ import VersionSelect, {
import TiDBLogoWithoutText from "media/logo/tidb-logo.svg";

interface LeftNavProps {
data: DocLeftNav;
data: RepoNav;
current: string;
name: string;
pathConfig: PathConfig;
Expand All @@ -44,11 +44,12 @@ export function LeftNavDesktop(props: LeftNavProps) {
<Box
sx={{
position: "sticky",
top: "5rem",
top: "80px",
height: "100%",
maxHeight: "calc(100vh - 7rem)",
maxHeight: "calc(100vh - 80px)",
boxSizing: "border-box",
overflowY: "auto",
padding: "28px 1rem",
padding: "20px 14px",
}}
>
{pathConfig.repo !== "tidbcloud" && (
Expand Down
Loading