mirror of
https://github.com/nix-community/noogle.git
synced 2024-09-11 09:15:53 +03:00
migrate to nextjs app router
This commit is contained in:
parent
b0af677201
commit
8a3cb24bf9
3
website/.vscode/settings.json
vendored
Normal file
3
website/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
@ -1,7 +1,31 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
// rehypePlugins: [
|
||||
// [
|
||||
// rehypeHighlight,
|
||||
// {
|
||||
// detect: true,
|
||||
// languages: { nix, haskell, bash, default: nix },
|
||||
// },
|
||||
// ],
|
||||
// [rehypeSlug, {}],
|
||||
// [rehypeAutolinkHeadings, { behavior: "wrap" }],
|
||||
// ],
|
||||
// remarkPlugins: [remarkHeadingId],
|
||||
// format: "md",
|
||||
// const remarkHeadingId = require("remark-heading-id");
|
||||
// const remarkFrontmatter = import("remark-frontmatter");
|
||||
// const withMDX = require("@next/mdx")({
|
||||
// options: {
|
||||
// remarkPlugins: [remarkHeadingId, remarkFrontmatter],
|
||||
// rehypePlugins: [],
|
||||
// },
|
||||
// extension: /\.mdx?$/,
|
||||
// });
|
||||
|
||||
const nextConfig = (phase, { defaultConfig }) => {
|
||||
const config = {
|
||||
compress: true,
|
||||
optimizeFonts: true,
|
||||
output: "export",
|
||||
reactStrictMode: true,
|
||||
swcMinify: true,
|
||||
@ -9,6 +33,7 @@ const nextConfig = (phase, { defaultConfig }) => {
|
||||
loader: "custom",
|
||||
},
|
||||
};
|
||||
|
||||
return config;
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,6 @@ in
|
||||
config.floco.packages.${ident}.${version} =
|
||||
let
|
||||
cfg = config.floco.packages.${ident}.${version};
|
||||
prefix = "models/data";
|
||||
in
|
||||
{
|
||||
# ---------------------------------------------------------------------------- #
|
||||
@ -49,9 +48,9 @@ in
|
||||
override.preBuild = ''
|
||||
export HOME=./home
|
||||
|
||||
${hooks.prepare "models/data"}
|
||||
${hooks.prepare "src/models/data"}
|
||||
|
||||
ls -la models/data
|
||||
ls -la src/models/data
|
||||
'';
|
||||
|
||||
tree =
|
||||
|
File diff suppressed because it is too large
Load Diff
10280
website/package-lock.json
generated
10280
website/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,20 +12,39 @@
|
||||
"@emotion/react": "^11.10.5",
|
||||
"@emotion/styled": "^11.10.5",
|
||||
"@fontsource/roboto": "^5.0.0",
|
||||
"@jsdevtools/rehype-toc": "^3.0.2",
|
||||
"@mdx-js/loader": "^3.0.0",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"@mui/icons-material": "^5.10.9",
|
||||
"@mui/material": "^5.10.13",
|
||||
"@next/mdx": "^14.0.3",
|
||||
"@types/mdx": "^2.0.10",
|
||||
"@vcarl/remark-headings": "^0.1.0",
|
||||
"highlight.js": "^11.7.0",
|
||||
"minisearch": "^6.0.1",
|
||||
"next": "^14.0.3",
|
||||
"next-mdx-remote": "^4.4.1",
|
||||
"notistack": "^3.0.0",
|
||||
"pagefind": "^1.0.4",
|
||||
"parse5": "^7.1.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-highlight": "^0.15.0",
|
||||
"react-mark.js": "^9.0.7",
|
||||
"react-markdown": "^9.0.0",
|
||||
"react-minisearch": "^6.0.2",
|
||||
"rehype": "^13.0.1",
|
||||
"rehype-autolink-headings": "^7.1.0",
|
||||
"rehype-highlight": "^7.0.0",
|
||||
"rehype-slug": "^6.0.0",
|
||||
"rehype-stringify": "^10.0.0",
|
||||
"remark-frontmatter": "^5.0.0",
|
||||
"remark-heading-id": "^1.0.1",
|
||||
"remark-parse": "^11.0.0",
|
||||
"remark-rehype": "^11.0.0",
|
||||
"remark-stringify": "^11.0.0",
|
||||
"seedrandom": "^3.0.5",
|
||||
"unified": "^11.0.4",
|
||||
"usehooks-ts": "^2.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -37,7 +56,6 @@
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.3",
|
||||
"@typescript-eslint/parser": "^6.7.3",
|
||||
"eslint": "8.50.0",
|
||||
"eslint-config-next": "^14.0.3",
|
||||
"typescript": "5.2.2"
|
||||
"eslint-config-next": "^14.0.3"
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
{ fmod, pkg, pkgs, hooks, ... }:
|
||||
pkgs.mkShell {
|
||||
buildInputs = [ fmod.config.floco.settings.nodePackage ];
|
||||
packages = [ fmod.config.floco.settings.nodePackage ];
|
||||
shellHook = ''
|
||||
${hooks.prepare "models/data"}
|
||||
${hooks.prepare "src/models/data"}
|
||||
|
||||
ID=${pkg.built.tree}
|
||||
currID=$(cat .floco/.node_modules_id 2> /dev/null)
|
||||
|
@ -1,13 +1,15 @@
|
||||
"use client";
|
||||
import { NixFunctions } from "@/components/NixFunctions/nixFunctions";
|
||||
import NixFunctions from "@/components/NixFunctions";
|
||||
import { usePageContext } from "@/components/pageContext";
|
||||
|
||||
export default function Home() {
|
||||
const { pageState, setPageStateVariable } = usePageContext();
|
||||
return (
|
||||
// <PageContextProvider>
|
||||
<NixFunctions
|
||||
pageState={pageState}
|
||||
setPageStateVariable={setPageStateVariable}
|
||||
/>
|
||||
// </PageContextProvider>
|
||||
);
|
||||
}
|
||||
|
107
website/src/app/ref/[...id]/page.tsx
Normal file
107
website/src/app/ref/[...id]/page.tsx
Normal file
@ -0,0 +1,107 @@
|
||||
// import { DocsFrontmatter, getMdxMeta } from "@/components/ListGroup";
|
||||
import {
|
||||
docsDir,
|
||||
extractHeadings,
|
||||
getMdxSource,
|
||||
mdxRenderOptions,
|
||||
} from "@/utils";
|
||||
import { Edit } from "@mui/icons-material";
|
||||
import { Box, Button, Typography } from "@mui/material";
|
||||
import fs from "fs";
|
||||
// import "highlight.js/styles/github-dark-dimmed.css";
|
||||
import "highlight.js/styles/github-dark.css";
|
||||
import { MDXRemote } from "next-mdx-remote/rsc";
|
||||
import Link from "next/link";
|
||||
import path from "path";
|
||||
|
||||
export async function generateStaticParams() {
|
||||
const files = fs.readdirSync(docsDir, {
|
||||
recursive: true,
|
||||
withFileTypes: true,
|
||||
encoding: "utf-8",
|
||||
});
|
||||
const paths: { id: string[] }[] = files
|
||||
.filter((f) => !f.isDirectory())
|
||||
.map((f) => {
|
||||
const dirname = path.relative(docsDir, f.path);
|
||||
const filename = path.parse(f.name).name;
|
||||
return {
|
||||
id: [...dirname.split("/"), filename],
|
||||
};
|
||||
});
|
||||
return paths;
|
||||
}
|
||||
|
||||
interface TocProps {
|
||||
mdxSource: Buffer;
|
||||
}
|
||||
|
||||
const Toc = async (props: TocProps) => {
|
||||
const { mdxSource } = props;
|
||||
const headings = await extractHeadings(mdxSource);
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
order: 2,
|
||||
width: "19rem",
|
||||
py: 4,
|
||||
px: 2,
|
||||
}}
|
||||
component={"aside"}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
pt: 4,
|
||||
pl: 2,
|
||||
}}
|
||||
>
|
||||
<Typography variant="subtitle1">Table of Contents</Typography>
|
||||
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
||||
{headings.map((h, idx) => (
|
||||
<Link key={idx} href={`#${h.id}`}>
|
||||
<Button
|
||||
fullWidth
|
||||
variant="text"
|
||||
sx={{
|
||||
justifyContent: "start",
|
||||
textTransform: "none",
|
||||
color: "text.secondary",
|
||||
pl: (h.level - 1) * 2,
|
||||
}}
|
||||
>
|
||||
{h.value}
|
||||
</Button>
|
||||
</Link>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
// Multiple versions of this page will be statically generated
|
||||
// using the `params` returned by `generateStaticParams`
|
||||
export default async function Page(props: { params: { id: string[] } }) {
|
||||
const { mdxSource } = await getMdxSource(props.params.id);
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ display: "flex" }}>
|
||||
<Toc mdxSource={mdxSource} />
|
||||
<Box sx={{ order: 1, width: "60rem", marginInline: "auto", py: 2 }}>
|
||||
<MDXRemote
|
||||
options={{
|
||||
parseFrontmatter: true,
|
||||
mdxOptions: mdxRenderOptions,
|
||||
}}
|
||||
source={mdxSource}
|
||||
/>
|
||||
<Button sx={{ textTransform: "none", my: 4 }} startIcon={<Edit />}>
|
||||
Edit source
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
36
website/src/app/ref/layout.tsx
Normal file
36
website/src/app/ref/layout.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import { NavSidebar } from "@/components/NavSidebar";
|
||||
import { Box } from "@mui/material";
|
||||
|
||||
export default async function Page({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<aside
|
||||
style={{
|
||||
position: "fixed",
|
||||
height: "100vh",
|
||||
overflowY: "scroll",
|
||||
overflowX: "hidden",
|
||||
left: 0,
|
||||
width: "19rem",
|
||||
}}
|
||||
>
|
||||
<NavSidebar />
|
||||
</aside>
|
||||
<Box
|
||||
sx={{
|
||||
ml: "25em",
|
||||
px: 2,
|
||||
py: 4,
|
||||
w: "100%",
|
||||
bgcolor: "background.paper",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</div>
|
||||
);
|
||||
}
|
26
website/src/client.ts
Normal file
26
website/src/client.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import seedrandom from "seedrandom";
|
||||
|
||||
const date = new Date();
|
||||
|
||||
const dayOfYear = (date: Date) => {
|
||||
const diff = Number(date) - Number(new Date(date.getFullYear(), 0, 0));
|
||||
return Math.floor(diff / 1000 / 60 / 60 / 24);
|
||||
};
|
||||
|
||||
const seed = dayOfYear(date).toString() + date.getFullYear().toString();
|
||||
const rng = seedrandom(seed);
|
||||
const FOTD_RND = rng();
|
||||
|
||||
type Config = {
|
||||
init?: number;
|
||||
};
|
||||
export function pseudoRandomIntInclusive(
|
||||
min: number,
|
||||
max: number,
|
||||
config?: Config
|
||||
) {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
const randomNumber = config?.init || FOTD_RND;
|
||||
return Math.floor(randomNumber * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive
|
||||
}
|
73
website/src/components/NavSidebar/ListCollapse.tsx
Normal file
73
website/src/components/NavSidebar/ListCollapse.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
"use client";
|
||||
import { ChevronRight, ExpandMore } from "@mui/icons-material";
|
||||
import {
|
||||
Collapse,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
} from "@mui/material";
|
||||
import { ReactNode, useState } from "react";
|
||||
|
||||
const borderStyle = {
|
||||
borderInlineStartStyle: "solid",
|
||||
borderInlineStartWidth: "1px",
|
||||
borderInlineStartColor: "#e4e4e7",
|
||||
ml: 2,
|
||||
pl: 2,
|
||||
};
|
||||
interface CollapseWrapperProps {
|
||||
children: ReactNode;
|
||||
name: string;
|
||||
position: number;
|
||||
}
|
||||
export const CollapseWrapper = (props: CollapseWrapperProps) => {
|
||||
const { children, name, position } = props;
|
||||
const [expandedKeys, setExpanded] = useState<string[]>([]);
|
||||
const isExpanded = expandedKeys.includes(name);
|
||||
return (
|
||||
<>
|
||||
<ListItem
|
||||
disablePadding
|
||||
disableGutters
|
||||
sx={{
|
||||
...(position > 0 ? borderStyle : undefined),
|
||||
}}
|
||||
>
|
||||
<ListItemButton
|
||||
disableGutters
|
||||
onClick={() => {
|
||||
setExpanded((s) =>
|
||||
isExpanded ? s.filter((n) => n !== name) : [...s, name]
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ListItemText
|
||||
primary={name}
|
||||
primaryTypographyProps={{
|
||||
sx: {
|
||||
fontWeight: 700,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<ListItemIcon sx={{ minWidth: "40px" }}>
|
||||
{isExpanded ? <ExpandMore /> : <ChevronRight />}
|
||||
</ListItemIcon>
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
|
||||
<Collapse in={isExpanded}>
|
||||
<List
|
||||
dense
|
||||
disablePadding
|
||||
sx={{
|
||||
...(position > 0 ? borderStyle : undefined),
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</List>
|
||||
</Collapse>
|
||||
</>
|
||||
);
|
||||
};
|
18
website/src/components/NavSidebar/ListEntry.tsx
Normal file
18
website/src/components/NavSidebar/ListEntry.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
"use client";
|
||||
import { ListItemButton } from "@mui/material";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
interface ListIndicatorProps {
|
||||
currentPath: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
export const ListEntry = (props: ListIndicatorProps) => {
|
||||
const { currentPath, children } = props;
|
||||
const pathname = usePathname();
|
||||
const selected = pathname === currentPath;
|
||||
return (
|
||||
<ListItemButton disableGutters selected={selected}>
|
||||
{children}
|
||||
</ListItemButton>
|
||||
);
|
||||
};
|
47
website/src/components/NavSidebar/ListGroup.tsx
Normal file
47
website/src/components/NavSidebar/ListGroup.tsx
Normal file
@ -0,0 +1,47 @@
|
||||
import { Group, getMdxMeta } from "@/utils";
|
||||
import { ListItem, ListItemText } from "@mui/material";
|
||||
import Link from "next/link";
|
||||
import { CollapseWrapper } from "./ListCollapse";
|
||||
import { ListEntry } from "./ListEntry";
|
||||
|
||||
interface ListGroupProps {
|
||||
grp: Group;
|
||||
position: number;
|
||||
}
|
||||
export const ListGroup = async (props: ListGroupProps) => {
|
||||
const { grp, position } = props;
|
||||
const sorted = Object.entries(grp).sort(([, v], [,]) =>
|
||||
Array.isArray(v) ? 1 : -1
|
||||
);
|
||||
|
||||
return sorted.map(async ([name, entry], idx) => {
|
||||
if (Array.isArray(entry)) {
|
||||
const matter = await getMdxMeta(entry);
|
||||
return (
|
||||
<Link key={`${idx}`} href={`/ref/${entry.join("/")}`}>
|
||||
<ListItem
|
||||
disablePadding
|
||||
disableGutters
|
||||
sx={{
|
||||
ml: 2,
|
||||
pl: 2,
|
||||
borderInlineStartStyle: "solid",
|
||||
borderInlineStartWidth: "1px",
|
||||
borderInlineStartColor: "#e4e4e7",
|
||||
}}
|
||||
>
|
||||
<ListEntry currentPath={`/ref/${entry.join("/")}`}>
|
||||
<ListItemText primary={matter.compiled.frontmatter.title} />
|
||||
</ListEntry>
|
||||
</ListItem>
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<CollapseWrapper key={idx} name={name} position={position}>
|
||||
<ListGroup grp={entry} position={position + 1} />
|
||||
</CollapseWrapper>
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
33
website/src/components/NavSidebar/index.tsx
Normal file
33
website/src/components/NavSidebar/index.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import { Group, generateStaticSidebarEntries, set } from "@/utils";
|
||||
import { Box, List, Paper, Typography } from "@mui/material";
|
||||
import { ListGroup } from "./ListGroup";
|
||||
|
||||
export const NavSidebar = async () => {
|
||||
const list = await generateStaticSidebarEntries();
|
||||
const grp: Group = list.reduce((acc, item) => {
|
||||
set(acc, item.id.join("."), item.id);
|
||||
return acc;
|
||||
}, {});
|
||||
return (
|
||||
<Paper sx={{ height: "100%" }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
py: 2,
|
||||
}}
|
||||
>
|
||||
<Typography variant="subtitle1" component="h3">
|
||||
References
|
||||
</Typography>
|
||||
</Box>
|
||||
<List
|
||||
sx={{ width: "100%", bgcolor: "background.paper" }}
|
||||
component="nav"
|
||||
disablePadding
|
||||
>
|
||||
<ListGroup grp={grp} position={0} />
|
||||
</List>
|
||||
</Paper>
|
||||
);
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
"use client";
|
||||
import { PageState, normalizePath } from "@/models/internals";
|
||||
import { DocItem } from "@/models/nix";
|
||||
import { byType, pipe } from "@/queries";
|
||||
|
31
website/src/components/fun.tsx
Normal file
31
website/src/components/fun.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
"use client";
|
||||
|
||||
import { pseudoRandomIntInclusive } from "@/client";
|
||||
import { useMemo, useState } from "react";
|
||||
import Markdown from "react-markdown";
|
||||
|
||||
interface FunctionOfTheDayProps {
|
||||
allPaths: { id: string[] }[];
|
||||
}
|
||||
export const FunctionOfTheDay = (props: FunctionOfTheDayProps) => {
|
||||
const { allPaths } = props;
|
||||
|
||||
const todaysIdx = useMemo(
|
||||
() => pseudoRandomIntInclusive(0, allPaths.length - 1),
|
||||
[allPaths.length]
|
||||
);
|
||||
const [idx] = useState<number>(todaysIdx);
|
||||
|
||||
// redirect(`ref/${allPaths[idx].id.join("/")}`);
|
||||
// const setFunctionOfTheDay = () => {
|
||||
// setIdx(todaysIdx);
|
||||
// };
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>{idx}</div>
|
||||
<div>{allPaths[idx].id.join("/")}</div>
|
||||
<Markdown>{allPaths[idx].id.join("\n")}</Markdown>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
"use client";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
|
@ -1,3 +1,4 @@
|
||||
"use client";
|
||||
import {
|
||||
InitialPageState,
|
||||
PageState,
|
||||
|
75
website/src/components/search.tsx
Normal file
75
website/src/components/search.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
"use client";
|
||||
import React, { useState } from "react";
|
||||
|
||||
export default function SearchPage() {
|
||||
const [query, setQuery] = React.useState("");
|
||||
const [results, setResults] = React.useState([]);
|
||||
|
||||
React.useEffect(() => {
|
||||
async function loadPagefind() {
|
||||
// @ts-ignore
|
||||
if (typeof window.pagefind === "undefined") {
|
||||
try {
|
||||
// @ts-ignore
|
||||
window.pagefind = await import(
|
||||
// @ts-expect-error pagefind.js generated after build
|
||||
/* webpackIgnore: true */ "/pagefind/pagefind.js"
|
||||
);
|
||||
// @ts-ignore
|
||||
console.log("setup:", window?.pagefind);
|
||||
} catch (e) {
|
||||
// @ts-ignore
|
||||
window.pagefind = { search: () => ({ results: [] }) };
|
||||
}
|
||||
}
|
||||
}
|
||||
loadPagefind();
|
||||
}, []);
|
||||
|
||||
async function handleSearch() {
|
||||
// @ts-ignore
|
||||
console.log("searching", window?.pagefind);
|
||||
// @ts-ignore
|
||||
if (window.pagefind) {
|
||||
// @ts-ignore
|
||||
const search = await window.pagefind.search(query);
|
||||
setResults(search.results);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("result", { results, query });
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
onInput={handleSearch}
|
||||
/>
|
||||
<div id="results">
|
||||
{results.map((result, index) => (
|
||||
// @ts-ignore
|
||||
<Result key={result.id} result={result} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Result({ result }: any) {
|
||||
const [data, setData] = useState(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
async function fetchData() {
|
||||
const data = await result.data();
|
||||
setData(data);
|
||||
}
|
||||
fetchData();
|
||||
}, [result]);
|
||||
|
||||
if (!data) return null;
|
||||
|
||||
// @ts-ignore
|
||||
return <div>{`${data.url}`}</div>;
|
||||
}
|
73
website/src/components/themeRegistry.tsx
Normal file
73
website/src/components/themeRegistry.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
// app/ThemeRegistry.tsx
|
||||
"use client";
|
||||
import { darkThemeOptions, lightThemeOptions } from "@/styles/theme";
|
||||
import createCache from "@emotion/cache";
|
||||
import { CacheProvider } from "@emotion/react";
|
||||
import { useMediaQuery } from "@mui/material";
|
||||
import CssBaseline from "@mui/material/CssBaseline";
|
||||
import { ThemeProvider, createTheme } from "@mui/material/styles";
|
||||
import { useServerInsertedHTML } from "next/navigation";
|
||||
import React, { ReactNode } from "react";
|
||||
|
||||
const lightTheme = createTheme(lightThemeOptions);
|
||||
const darkTheme = createTheme(darkThemeOptions);
|
||||
|
||||
// This implementation is from emotion-js
|
||||
// https://github.com/emotion-js/emotion/issues/2928#issuecomment-1319747902
|
||||
export default function ThemeRegistry(props: {
|
||||
children: ReactNode;
|
||||
options: any;
|
||||
}) {
|
||||
const userPrefersDarkmode = useMediaQuery("(prefers-color-scheme: dark)");
|
||||
|
||||
const { options, children } = props;
|
||||
|
||||
const [{ cache, flush }] = React.useState(() => {
|
||||
const cache = createCache(options);
|
||||
cache.compat = true;
|
||||
const prevInsert = cache.insert;
|
||||
let inserted: string[] = [];
|
||||
cache.insert = (...args) => {
|
||||
const serialized = args[1];
|
||||
if (cache.inserted[serialized.name] === undefined) {
|
||||
inserted.push(serialized.name);
|
||||
}
|
||||
return prevInsert(...args);
|
||||
};
|
||||
const flush = () => {
|
||||
const prevInserted = inserted;
|
||||
inserted = [];
|
||||
return prevInserted;
|
||||
};
|
||||
return { cache, flush };
|
||||
});
|
||||
|
||||
useServerInsertedHTML(() => {
|
||||
const names = flush();
|
||||
if (names.length === 0) {
|
||||
return null;
|
||||
}
|
||||
let styles = "";
|
||||
for (const name of names) {
|
||||
styles += cache.inserted[name];
|
||||
}
|
||||
return (
|
||||
<style
|
||||
key={cache.key}
|
||||
data-emotion={`${cache.key} ${names.join(" ")}`}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: options.prepend ? `@layer emotion {${styles}}` : styles,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<CacheProvider value={cache}>
|
||||
<ThemeProvider theme={userPrefersDarkmode ? darkTheme : lightTheme}>
|
||||
<CssBaseline />
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
</CacheProvider>
|
||||
);
|
||||
}
|
16
website/src/docs/builtins/builtins-break.md
Normal file
16
website/src/docs/builtins/builtins-break.md
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
title: builtins.break
|
||||
editUrl: false
|
||||
description: builtins.break
|
||||
sidebar:
|
||||
|
||||
badge:
|
||||
text: Builtin
|
||||
variant: note
|
||||
|
||||
order: 0
|
||||
---
|
||||
|
||||
In debug mode (enabled using `--debugger`), pause Nix expression evaluation and enter the REPL.
|
||||
Otherwise, return the argument `v`.
|
||||
|
41
website/src/docs/lib/attrsets/lib-attrsets-attrByPath.md
Normal file
41
website/src/docs/lib/attrsets/lib-attrsets-attrByPath.md
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
title: lib.attrsets.attrByPath
|
||||
editUrl: https://www.github.com/hsjobeki/nixpkgs/tree/migrate-doc-comments/lib/attrsets.nix#L45C5
|
||||
description: lib.attrsets.attrByPath
|
||||
sidebar:
|
||||
|
||||
order: 7
|
||||
---
|
||||
|
||||
Return an attribute from nested attribute sets.
|
||||
|
||||
# Example
|
||||
|
||||
```nix
|
||||
x = { a = { b = 3; }; }
|
||||
# ["a" "b"] is equivalent to x.a.b
|
||||
# 6 is a default value to return if the path does not exist in attrset
|
||||
attrByPath ["a" "b"] 6 x
|
||||
=> 3
|
||||
attrByPath ["z" "z"] 6 x
|
||||
=> 6
|
||||
```
|
||||
|
||||
# Type
|
||||
|
||||
```
|
||||
attrByPath :: [String] -> Any -> AttrSet -> Any
|
||||
```
|
||||
|
||||
# Arguments
|
||||
|
||||
- [attrPath] A list of strings representing the attribute path to return from `set`
|
||||
- [default] Default value if `attrPath` does not resolve to an existing value
|
||||
- [set] The nested attribute set to select values from
|
||||
|
||||
|
||||
# Aliases
|
||||
|
||||
- [lib.attrByPath](/reference/lib/lib-attrbypath)
|
||||
|
||||
|
24
website/src/docs/lib/attrsets/lib-attrsets-attrNames.md
Normal file
24
website/src/docs/lib/attrsets/lib-attrsets-attrNames.md
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
title: lib.attrsets.attrNames
|
||||
editUrl: false
|
||||
description: lib.attrsets.attrNames
|
||||
sidebar:
|
||||
|
||||
badge:
|
||||
text: Builtin
|
||||
variant: note
|
||||
|
||||
order: 7
|
||||
---
|
||||
|
||||
Return the names of the attributes in the set *set* in an
|
||||
alphabetically sorted list. For instance, `builtins.attrNames { y
|
||||
= 1; x = "foo"; }` evaluates to `[ "x" "y" ]`.
|
||||
|
||||
|
||||
# Aliases
|
||||
|
||||
- [builtins.attrNames](/reference/builtins/builtins-attrnames)
|
||||
- [lib.attrNames](/reference/lib/lib-attrnames)
|
||||
|
||||
|
13
website/src/docs/pkgs/pkgs-buildLinux.md
Normal file
13
website/src/docs/pkgs/pkgs-buildLinux.md
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
title: pkgs.buildLinux
|
||||
editUrl: https://www.github.com/hsjobeki/nixpkgs/tree/migrate-doc-comments/pkgs/top-level/linux-kernels.nix#L716C16
|
||||
description: pkgs.buildLinux
|
||||
sidebar:
|
||||
|
||||
order: 8
|
||||
---
|
||||
|
||||
<a href="https://www.github.com/hsjobeki/nixpkgs/tree/migrate-doc-comments/pkgs/top-level/linux-kernels.nix#L716C16">Contribute Now!</a>
|
||||
|
||||
|
||||
|
10
website/src/docs/pkgs/stdenv/pkgs-stdenv-mkDerivation.md
Normal file
10
website/src/docs/pkgs/stdenv/pkgs-stdenv-mkDerivation.md
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
title: pkgs.stdenv.mkDerivation
|
||||
editUrl: https://www.github.com/hsjobeki/nixpkgs/tree/migrate-doc-comments/pkgs/stdenv/generic/make-derivation.nix#L548C3
|
||||
description: pkgs.stdenv.mkDerivation
|
||||
sidebar:
|
||||
|
||||
order: 7
|
||||
---
|
||||
|
||||
<a href="https://www.github.com/hsjobeki/nixpkgs/tree/migrate-doc-comments/pkgs/stdenv/generic/make-derivation.nix#L548C3">Contribute Now!</a>
|
@ -1,19 +1,9 @@
|
||||
import { MetaData } from "../nix";
|
||||
import nixBuiltins from "./builtins.json";
|
||||
import nixLibs from "./lib.json";
|
||||
import nixTrivialBuilders from "./trivial-builders.json";
|
||||
// const mock = {
|
||||
// id: "mock",
|
||||
// category: "mock",
|
||||
// name: "mock",
|
||||
// fn_type: null,
|
||||
// description: "No data yet in dev mode",
|
||||
// example: null,
|
||||
// line: null,
|
||||
// };
|
||||
import nixTrivialBuilders from "./build_support.json" assert { type: "json" };
|
||||
import nixBuiltins from "./builtins.json" assert { type: "json" };
|
||||
import nixLibs from "./lib.json" assert { type: "json" };
|
||||
|
||||
export const data: MetaData = [
|
||||
// mock,
|
||||
...(nixLibs as MetaData),
|
||||
...(nixBuiltins as MetaData),
|
||||
...(nixTrivialBuilders as MetaData),
|
||||
|
160
website/src/utils.ts
Normal file
160
website/src/utils.ts
Normal file
@ -0,0 +1,160 @@
|
||||
import fs from "fs";
|
||||
import bash from "highlight.js/lib/languages/bash";
|
||||
import haskell from "highlight.js/lib/languages/haskell";
|
||||
import nix from "highlight.js/lib/languages/nix";
|
||||
import "highlight.js/styles/github-dark-dimmed.css";
|
||||
import { SerializeOptions } from "next-mdx-remote/dist/types";
|
||||
import { CompileMDXResult, compileMDX } from "next-mdx-remote/rsc";
|
||||
import { parse, serialize } from "parse5";
|
||||
import path from "path";
|
||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||
import rehypeHighlight from "rehype-highlight";
|
||||
import rehypeSlug from "rehype-slug";
|
||||
import rehypeStringify from "rehype-stringify";
|
||||
// @ts-expect-error: Could not find type declaration file.
|
||||
import remarkHeadingId from "remark-heading-id";
|
||||
import remarkParse from "remark-parse";
|
||||
import remarkRehype from "remark-rehype";
|
||||
import { unified } from "unified";
|
||||
|
||||
/**
|
||||
* Function to generate a set from a path in lodash style
|
||||
* ```
|
||||
* set({}, "foo.bar", "value");
|
||||
* ->
|
||||
* {
|
||||
* foo: {
|
||||
* bar: "value"
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* @param obj Object in which to insert records
|
||||
* @param path Path/String in "." seperated form
|
||||
* @param value Any value to insert.
|
||||
*/
|
||||
export function set(obj: Record<string, any>, path: string, value: any): void {
|
||||
let schema = obj; // a moving reference to internal objects within obj
|
||||
const pList = path.split(".");
|
||||
const len = pList.length;
|
||||
for (let i = 0; i < len - 1; i++) {
|
||||
const elem = pList[i];
|
||||
if (!schema[elem]) schema[elem] = {};
|
||||
schema = schema[elem];
|
||||
}
|
||||
schema[pList[len - 1]] = value;
|
||||
}
|
||||
|
||||
export const docsDir = path.join(process.cwd(), "src/docs");
|
||||
|
||||
export async function generateStaticSidebarEntries() {
|
||||
const files = fs.readdirSync(docsDir, {
|
||||
recursive: true,
|
||||
withFileTypes: true,
|
||||
encoding: "utf-8",
|
||||
});
|
||||
const paths: { id: string[] }[] = await Promise.all(
|
||||
files
|
||||
.filter((f) => !f.isDirectory())
|
||||
.map(async (f) => {
|
||||
const dirname = path.relative(docsDir, f.path);
|
||||
const filename = path.parse(f.name).name;
|
||||
const id = [...dirname.split("/"), filename];
|
||||
return {
|
||||
id,
|
||||
};
|
||||
})
|
||||
);
|
||||
return paths;
|
||||
}
|
||||
|
||||
export type DocsFrontmatter = { title: String };
|
||||
|
||||
export const getMdxMeta = async (
|
||||
parts: string[]
|
||||
): Promise<{
|
||||
mdxSource: string;
|
||||
compiled: CompileMDXResult<DocsFrontmatter>;
|
||||
}> => {
|
||||
const location = path.join(docsDir, `${parts.map(decodeURI).join("/")}.md`);
|
||||
const source = fs.readFileSync(location, { encoding: "utf-8" });
|
||||
|
||||
return {
|
||||
mdxSource: source,
|
||||
compiled: await compileMDX({
|
||||
source,
|
||||
options: {
|
||||
parseFrontmatter: true,
|
||||
mdxOptions: {
|
||||
format: "md",
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
export const getMdxSource = async (parts: string[]) => {
|
||||
const decoded = parts.map(decodeURI).join("/");
|
||||
const location = path.join(docsDir, `${decoded}.md`);
|
||||
const source = fs.readFileSync(location);
|
||||
return {
|
||||
mdxSource: source,
|
||||
};
|
||||
};
|
||||
|
||||
export type Group = {
|
||||
[name: string]: string[] | Group;
|
||||
};
|
||||
|
||||
type Heading = {
|
||||
level: number;
|
||||
value: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const extractHeadings = async (content: Buffer): Promise<Heading[]> => {
|
||||
const processor = unified()
|
||||
.use(remarkParse)
|
||||
.use(remarkHeadingId)
|
||||
.use(remarkRehype)
|
||||
.use(rehypeSlug)
|
||||
.use(rehypeStringify);
|
||||
|
||||
const result = await processor.process(content);
|
||||
|
||||
const document = parse(result.value.toString());
|
||||
|
||||
const headings: Heading[] = [];
|
||||
const processNode = (node: any) => {
|
||||
if (
|
||||
node?.tagName &&
|
||||
["h1", "h2", "h3", "h4", "h5", "h6"].some((hN) => node?.tagName === hN)
|
||||
) {
|
||||
const nm = node.tagName.slice(1);
|
||||
const level = parseInt(nm, 10);
|
||||
const id = node?.attrs?.find((attr: any) => attr?.name === "id")?.value;
|
||||
const value: string = serialize(node);
|
||||
headings.push({ level, id, value });
|
||||
}
|
||||
if (node.childNodes) {
|
||||
node.childNodes.forEach(processNode);
|
||||
}
|
||||
};
|
||||
processNode(document);
|
||||
return headings as Heading[];
|
||||
};
|
||||
|
||||
export const mdxRenderOptions: SerializeOptions["mdxOptions"] = {
|
||||
rehypePlugins: [
|
||||
[
|
||||
rehypeHighlight,
|
||||
{
|
||||
detect: true,
|
||||
languages: { nix, haskell, bash, default: nix },
|
||||
},
|
||||
],
|
||||
[rehypeSlug, {}],
|
||||
[rehypeAutolinkHeadings, { behavior: "wrap" }],
|
||||
],
|
||||
remarkPlugins: [remarkHeadingId],
|
||||
format: "md",
|
||||
} as SerializeOptions["mdxOptions"];
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"lib": [
|
||||
@ -31,8 +32,8 @@
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
|
Loading…
Reference in New Issue
Block a user