diff --git a/docs/src/components/Code.jsx b/docs/src/components/Code.jsx
deleted file mode 100644
index 4bfc80ab..00000000
--- a/docs/src/components/Code.jsx
+++ /dev/null
@@ -1,298 +0,0 @@
-import {
- Children,
- createContext,
- useContext,
- useEffect,
- useRef,
- useState,
-} from "react";
-import { Tab } from "@headlessui/react";
-import clsx from "clsx";
-import { create } from "zustand";
-
-import { Tag } from "@/components/Tag";
-
-const languageNames = {
- js: "JavaScript",
- ts: "TypeScript",
- javascript: "JavaScript",
- typescript: "TypeScript",
- php: "PHP",
- python: "Python",
- ruby: "Ruby",
- go: "Go",
-};
-
-function getPanelTitle({ title, language }) {
- return title ?? languageNames[language] ?? "Code";
-}
-
-function ClipboardIcon(props) {
- return (
-
-
-
-
- );
-}
-
-function CopyButton({ code }) {
- let [copyCount, setCopyCount] = useState(0);
- let copied = copyCount > 0;
-
- useEffect(() => {
- if (copyCount > 0) {
- let timeout = setTimeout(() => setCopyCount(0), 1000);
- return () => {
- clearTimeout(timeout);
- };
- }
- }, [copyCount]);
-
- return (
- {
- window.navigator.clipboard.writeText(code).then(() => {
- setCopyCount((count) => count + 1);
- });
- }}
- >
-
-
- Copy
-
-
- Copied!
-
-
- );
-}
-
-function CodePanelHeader({ tag, label }) {
- if (!tag && !label) {
- return null;
- }
-
- return (
-
- {tag && (
-
- {tag}
-
- )}
- {tag && label && (
-
- )}
- {label && (
-
{label}
- )}
-
- );
-}
-
-function CodePanel({ tag, label, code, children }) {
- let child = Children.only(children);
-
- return (
-
- );
-}
-
-function CodeGroupHeader({ title, children, selectedIndex }) {
- let hasTabs = Children.count(children) > 1;
-
- if (!title && !hasTabs) {
- return null;
- }
-
- return (
-
- {title && (
-
- {title}
-
- )}
- {hasTabs && (
-
- {Children.map(children, (child, childIndex) => (
-
- {getPanelTitle(child.props)}
-
- ))}
-
- )}
-
- );
-}
-
-function CodeGroupPanels({ children, ...props }) {
- let hasTabs = Children.count(children) > 1;
-
- if (hasTabs) {
- return (
-
- {Children.map(children, (child) => (
-
- {child}
-
- ))}
-
- );
- }
-
- return {children} ;
-}
-
-function usePreventLayoutShift() {
- let positionRef = useRef();
- let rafRef = useRef();
-
- useEffect(() => {
- return () => {
- window.cancelAnimationFrame(rafRef.current);
- };
- }, []);
-
- return {
- positionRef,
- preventLayoutShift(callback) {
- let initialTop = positionRef.current.getBoundingClientRect().top;
-
- callback();
-
- rafRef.current = window.requestAnimationFrame(() => {
- let newTop = positionRef.current.getBoundingClientRect().top;
- window.scrollBy(0, newTop - initialTop);
- });
- },
- };
-}
-
-const usePreferredLanguageStore = create((set) => ({
- preferredLanguages: [],
- addPreferredLanguage: (language) =>
- set((state) => ({
- preferredLanguages: [
- ...state.preferredLanguages.filter(
- (preferredLanguage) => preferredLanguage !== language
- ),
- language,
- ],
- })),
-}));
-
-function useTabGroupProps(availableLanguages) {
- let { preferredLanguages, addPreferredLanguage } =
- usePreferredLanguageStore();
- let [selectedIndex, setSelectedIndex] = useState(0);
- let activeLanguage = [...availableLanguages].sort(
- (a, z) => preferredLanguages.indexOf(z) - preferredLanguages.indexOf(a)
- )[0];
- let languageIndex = availableLanguages.indexOf(activeLanguage);
- let newSelectedIndex = languageIndex === -1 ? selectedIndex : languageIndex;
- if (newSelectedIndex !== selectedIndex) {
- setSelectedIndex(newSelectedIndex);
- }
-
- let { positionRef, preventLayoutShift } = usePreventLayoutShift();
-
- return {
- as: "div",
- ref: positionRef,
- selectedIndex,
- onChange: (newSelectedIndex) => {
- preventLayoutShift(() =>
- addPreferredLanguage(availableLanguages[newSelectedIndex])
- );
- },
- };
-}
-
-const CodeGroupContext = createContext(false);
-
-export function CodeGroup({ children, title, ...props }) {
- let languages = Children.map(children, (child) => getPanelTitle(child.props));
- let tabGroupProps = useTabGroupProps(languages);
- let hasTabs = Children.count(children) > 1;
- let Container = hasTabs ? Tab.Group : "div";
- let containerProps = hasTabs ? tabGroupProps : {};
- let headerProps = hasTabs
- ? { selectedIndex: tabGroupProps.selectedIndex }
- : {};
-
- return (
-
-
-
- {children}
-
- {children}
-
-
- );
-}
-
-export function Code({ children, ...props }) {
- let isGrouped = useContext(CodeGroupContext);
-
- if (isGrouped) {
- return
;
- }
-
- return {children}
;
-}
-
-export function Pre({ children, ...props }) {
- let isGrouped = useContext(CodeGroupContext);
-
- if (isGrouped) {
- return children;
- }
-
- return {children} ;
-}
diff --git a/docs/src/components/Tag.jsx b/docs/src/components/Tag.jsx
deleted file mode 100644
index fb411b75..00000000
--- a/docs/src/components/Tag.jsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import clsx from "clsx";
-
-const variantStyles = {
- medium: "rounded-lg px-1.5 ring-1 ring-inset",
-};
-
-const colorStyles = {
- emerald: {
- small: "text-emerald-500 dark:text-emerald-400",
- medium:
- "ring-emerald-300 dark:ring-emerald-400/30 bg-emerald-400/10 text-emerald-500 dark:text-emerald-400",
- },
- sky: {
- small: "text-sky-500",
- medium:
- "ring-sky-300 bg-sky-400/10 text-sky-500 dark:ring-sky-400/30 dark:bg-sky-400/10 dark:text-sky-400",
- },
- amber: {
- small: "text-amber-500",
- medium:
- "ring-amber-300 bg-amber-400/10 text-amber-500 dark:ring-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400",
- },
- rose: {
- small: "text-red-500 dark:text-rose-500",
- medium:
- "ring-rose-200 bg-rose-50 text-red-500 dark:ring-rose-500/20 dark:bg-rose-400/10 dark:text-rose-400",
- },
- zinc: {
- small: "text-zinc-400 dark:text-zinc-500",
- medium:
- "ring-zinc-200 bg-zinc-50 text-zinc-500 dark:ring-zinc-500/20 dark:bg-zinc-400/10 dark:text-zinc-400",
- },
-};
-
-const valueColorMap = {
- get: "emerald",
- post: "sky",
- put: "amber",
- delete: "rose",
-};
-
-export function Tag({
- children,
- variant = "medium",
- color = valueColorMap[children.toLowerCase()] ?? "emerald",
-}) {
- return (
-
- {children}
-
- );
-}
diff --git a/docs/src/components/mdx.tsx b/docs/src/components/mdx.tsx
index c90c0035..b963d577 100644
--- a/docs/src/components/mdx.tsx
+++ b/docs/src/components/mdx.tsx
@@ -1,8 +1,7 @@
import clsx from "clsx";
-export { CodeGroup, Code as code, Pre as pre } from "@/components/Code";
type ParentComponentProps = {
- children: React.ReactNode;
+ children?: React.ReactNode;
};
export function Row({ children }: ParentComponentProps) {
@@ -29,3 +28,21 @@ export function Col({ children, sticky = false }: ColProps) {
);
}
+
+export function code({ children, ...props }: ParentComponentProps) {
+ return children ? (
+
+ ) : (
+
+ );
+}
+
+export function pre({ children, ...props }: ParentComponentProps) {
+ return (
+
+ );
+}
diff --git a/docs/src/mdx/rehype.mjs b/docs/src/mdx/rehype.mjs
index a57309aa..5936bf4c 100644
--- a/docs/src/mdx/rehype.mjs
+++ b/docs/src/mdx/rehype.mjs
@@ -20,11 +20,11 @@ function rehypeParseCodeBlocks() {
}
let highlighter
-
+const theme = await shiki.loadTheme("themes/github-light.json");
function rehypeShiki() {
return async (tree) => {
highlighter =
- highlighter ?? (await shiki.getHighlighter({ theme: 'css-variables' }))
+ highlighter ?? (await shiki.getHighlighter({ theme }))
visit(tree, 'element', (node) => {
if (node.tagName === 'pre' && node.children[0]?.tagName === 'code') {
diff --git a/docs/src/pages/index.mdx b/docs/src/pages/index.mdx
index 68534ab3..f840e357 100644
--- a/docs/src/pages/index.mdx
+++ b/docs/src/pages/index.mdx
@@ -7,7 +7,7 @@ import { Selfie } from "@/components/Selfie";
Sure, you could write your assertions like this.
-```
+```java
@Test
public void login() {
given().redirects().follow(false)
@@ -19,7 +19,7 @@ public void login() {
But isn't this easier to read? And also more complete?
-```
+```java
@Test
public void login() {
expectSelfie(
@@ -37,7 +37,7 @@ public void login() {
The only reason we don't test that way already is that it's too tedious to write out that big string literal. Buf if you write this...
-```
+```java
@Test
public void login() {
expectSelfie(
@@ -50,7 +50,7 @@ public void login() {
It's like a printf directly into your code. And it's not just for strings, it's for any literal.
-```
+```java
@Test
public void preventCssBloat() {
int size = expectSelfie(get("/index.css").length).toBe(5_236);
@@ -64,7 +64,7 @@ public void preventCssBloat() {
Some snapshots are so big that it would be cumbersome to put them inline into your test code. So selfie helps you put them on disk.
-```
+```java
@Test public void gzipFavicon() {
expectSelfie(get("/favicon.ico", ContentEncoding.GZIP)).toMatchDisk();
}
@@ -77,21 +77,24 @@ Some snapshots are so big that it would be cumbersome to put them inline into yo
This will generate a snapshot file like so:
-```
+```html
╔═ gzipFavicon ═╗ base64 length 823 bytes
-H4sIAAAAAAAA/8pIzcnJVyjPL8pJUQQAlQYXAAAA
-╔═ orderFlow/initial ═╗
-
- Submit order
-
+H4sIAAAAAAAA/8pIzcnJVyjPL8pJUQQAlQYXAAAA ╔═ orderFlow/initial ═╗
+
+
+ Submit order
+
+
╔═ orderFlow/ordered ═╗
-
- Thanks for your business!
-
- Order information
- Tracking #ABC123
-
-
+
+
+ Thanks for your business!
+
+ Order information
+ Tracking #ABC123
+
+
+
```
TODO.
diff --git a/docs/src/styles/tailwind.css b/docs/src/styles/tailwind.css
index ab2e10c2..0c04e047 100644
--- a/docs/src/styles/tailwind.css
+++ b/docs/src/styles/tailwind.css
@@ -12,4 +12,18 @@
@apply text-lg;
@apply desktop:text-2xl;
}
+
+ :root {
+ --shiki-color-text: #BBB;
+ --shiki-color-background: #EEE;
+ --shiki-token-constant: #ff8866;
+ --shiki-token-string: #8855ff;
+ --shiki-token-comment: #BBB;
+ --shiki-token-keyword: #0099ff;
+ --shiki-token-parameter: #33cccc;
+ --shiki-token-function: #FFAA00;
+ --shiki-token-string-expression: #8855ff;
+ --shiki-token-punctuation: #BBB;
+ --shiki-token-link: #0099ff;
+ }
}
diff --git a/docs/tailwind.config.js b/docs/tailwind.config.js
index 521bf63a..d4bec14c 100644
--- a/docs/tailwind.config.js
+++ b/docs/tailwind.config.js
@@ -8,6 +8,7 @@ module.exports = {
blue: "#63B9E3",
green: "#78ACAE",
red: "#E35C61",
+ grey: "#EEE",
},
boxShadow: {
button: "2px 2px 1px #4D4D4D",