@@ -2,6 +2,9 @@ import type * as Preset from "@docusaurus/preset-classic"
|
||||
import type { Config } from "@docusaurus/types"
|
||||
import { themes as prismThemes } from "prism-react-renderer"
|
||||
|
||||
import githubDark from "./src/prism/github-dark"
|
||||
import remarkLineNumbers from "./src/remark/line-numbers"
|
||||
|
||||
// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)
|
||||
|
||||
const config: Config = {
|
||||
@@ -43,6 +46,7 @@ const config: Config = {
|
||||
sidebarPath: "./sidebars.ts",
|
||||
editUrl:
|
||||
"https://github.com/Thiladev/effect-view/tree/main/packages/docs/",
|
||||
remarkPlugins: [remarkLineNumbers],
|
||||
lastVersion: "current",
|
||||
versions: {
|
||||
current: {
|
||||
@@ -140,7 +144,7 @@ const config: Config = {
|
||||
},
|
||||
prism: {
|
||||
theme: prismThemes.github,
|
||||
darkTheme: prismThemes.oneDark,
|
||||
darkTheme: githubDark,
|
||||
},
|
||||
} satisfies Preset.ThemeConfig,
|
||||
}
|
||||
|
||||
@@ -131,3 +131,78 @@ samp {
|
||||
background: var(--ev-zinc-900);
|
||||
border: 1px solid var(--ev-zinc-800);
|
||||
}
|
||||
|
||||
/* ---------- Code blocks ---------- */
|
||||
/* One quiet, low-contrast surface - matches effect.website: a subtle step
|
||||
off the page background, not a loud bordered card. */
|
||||
|
||||
.theme-code-block {
|
||||
--ifm-pre-padding: 1.25rem;
|
||||
background: var(--ev-zinc-50);
|
||||
border: 1px solid var(--ev-zinc-200);
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 1.5px 1.5px 3px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .theme-code-block {
|
||||
background: var(--ev-zinc-900);
|
||||
border-color: var(--ev-zinc-800);
|
||||
}
|
||||
|
||||
/* The Prism theme sets its own (much louder) background inline - drop it
|
||||
so the whole frame reads as one surface instead of a title/body seam. */
|
||||
.theme-code-block pre.thin-scrollbar {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
/* Title renders only when a `title="..."` fence meta is present */
|
||||
.theme-code-block:has(> div + div) > div:first-child {
|
||||
background: transparent;
|
||||
color: var(--ev-zinc-500);
|
||||
font-family: var(--ifm-font-family-monospace);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 500;
|
||||
padding: 0.9rem 1.4rem 0;
|
||||
}
|
||||
|
||||
.theme-code-block pre.thin-scrollbar {
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
[class*="buttonGroup_"] button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 0.35rem;
|
||||
color: var(--ev-zinc-500);
|
||||
}
|
||||
|
||||
[class*="buttonGroup_"] button:hover {
|
||||
background: var(--ev-zinc-100);
|
||||
color: var(--ev-zinc-800);
|
||||
}
|
||||
|
||||
[data-theme="dark"] [class*="buttonGroup_"] button:hover {
|
||||
background: var(--ev-zinc-900);
|
||||
color: var(--ev-zinc-100);
|
||||
}
|
||||
|
||||
[class*="codeLineNumber_"] {
|
||||
border: none;
|
||||
color: var(--ev-zinc-400);
|
||||
padding-inline: 1.25rem 1rem !important;
|
||||
text-align: right !important;
|
||||
}
|
||||
|
||||
[data-theme="dark"] [class*="codeLineNumber_"] {
|
||||
color: var(--ev-zinc-600);
|
||||
}
|
||||
|
||||
[class*="codeLineContent_"] {
|
||||
border-inline-start: 1px solid rgba(113, 113, 122, 0.2);
|
||||
padding-inline-start: 1.25rem;
|
||||
}
|
||||
|
||||
[class*="codeLineNumber_"]::before {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
@@ -280,15 +280,16 @@
|
||||
}
|
||||
|
||||
.codeWindow :global(.theme-code-block) {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.codeWindow :global(.theme-code-block pre) {
|
||||
.codeWindow :global(.theme-code-block pre.thin-scrollbar) {
|
||||
background: var(--home-terminal-bg) !important;
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.62;
|
||||
font-size: 0.8rem !important;
|
||||
line-height: 1.62 !important;
|
||||
max-height: none;
|
||||
padding: 1.4rem 1.6rem !important;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { PrismTheme } from "prism-react-renderer"
|
||||
|
||||
/**
|
||||
* Matches the classic "GitHub Dark" token palette effect.website uses for
|
||||
* its dark-mode code blocks (extracted from their rendered token styles) -
|
||||
* prism-react-renderer doesn't ship this one as a preset.
|
||||
*/
|
||||
const githubDark: PrismTheme = {
|
||||
plain: {
|
||||
color: "#e1e4e8",
|
||||
backgroundColor: "transparent",
|
||||
},
|
||||
styles: [
|
||||
{
|
||||
types: ["comment", "prolog", "doctype", "cdata"],
|
||||
style: { color: "#6a737d" },
|
||||
},
|
||||
{
|
||||
types: ["punctuation", "operator", "entity", "url", "variable"],
|
||||
style: { color: "#e1e4e8" },
|
||||
},
|
||||
{
|
||||
types: [
|
||||
"number",
|
||||
"boolean",
|
||||
"constant",
|
||||
"symbol",
|
||||
"deleted",
|
||||
"class-name",
|
||||
"maybe-class-name",
|
||||
"builtin",
|
||||
],
|
||||
style: { color: "#79b8ff" },
|
||||
},
|
||||
{
|
||||
types: ["selector", "attr-name", "string", "char", "inserted", "attr-value"],
|
||||
style: { color: "#9ecbff" },
|
||||
},
|
||||
{
|
||||
types: ["atrule", "keyword"],
|
||||
style: { color: "#f97583" },
|
||||
},
|
||||
{
|
||||
types: ["function", "method"],
|
||||
style: { color: "#b392f0" },
|
||||
},
|
||||
{
|
||||
types: ["regex", "important"],
|
||||
style: { color: "#ffab70" },
|
||||
},
|
||||
{
|
||||
types: ["tag"],
|
||||
style: { color: "#85e89d" },
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export default githubDark
|
||||
@@ -0,0 +1,38 @@
|
||||
const numberedLanguages = new Set(["ts", "tsx", "js", "jsx"])
|
||||
|
||||
interface MdastNode {
|
||||
type: string
|
||||
lang?: string
|
||||
meta?: string | null
|
||||
value?: string
|
||||
children?: MdastNode[]
|
||||
}
|
||||
|
||||
function visitCodeNodes(node: MdastNode, onCode: (code: MdastNode) => void): void {
|
||||
if (!node.children) return
|
||||
for (const child of node.children) {
|
||||
if (child.type === "code") onCode(child)
|
||||
visitCodeNodes(child, onCode)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on line numbers for multi-line ts/tsx/js/jsx fences that don't
|
||||
* already opt in or out, matching Effect's docs code block presentation.
|
||||
*/
|
||||
export default function remarkLineNumbers() {
|
||||
return (tree: MdastNode) => {
|
||||
visitCodeNodes(tree, (code) => {
|
||||
const lang = (code.lang ?? "").toLowerCase()
|
||||
if (!numberedLanguages.has(lang)) return
|
||||
|
||||
const meta = code.meta ?? ""
|
||||
if (/showLineNumbers/.test(meta)) return
|
||||
|
||||
const lineCount = (code.value ?? "").split("\n").length
|
||||
if (lineCount <= 1) return
|
||||
|
||||
code.meta = `${meta} showLineNumbers`.trim()
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user