blodemd 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dev-server/app/favicon.ico +0 -0
- package/dist/cli.mjs +370 -286
- package/dist/cli.mjs.map +1 -1
- package/docs/app/globals.css +1 -1
- package/docs/components/animate-ui/primitives/buttons/button.tsx +14 -0
- package/docs/components/docs/copy-page-menu.tsx +19 -3
- package/docs/components/docs/doc-shell.tsx +3 -3
- package/docs/components/mdx/steps.tsx +1 -1
- package/docs/components/ui/copy-button.tsx +122 -0
- package/docs/components/ui/site-footer.tsx +39 -0
- package/docs/lib/config.ts +7 -0
- package/docs/lib/tenancy.ts +36 -8
- package/package.json +2 -2
- package/packages/@repo/models/dist/docs-config.d.ts +3 -0
- package/packages/@repo/models/dist/docs-config.d.ts.map +1 -1
- package/packages/@repo/models/dist/docs-config.js +6 -0
- package/packages/@repo/models/src/docs-config.ts +6 -0
- package/packages/@repo/previewing/dist/index.d.ts +1 -0
- package/packages/@repo/previewing/dist/index.d.ts.map +1 -1
- package/packages/@repo/previewing/dist/index.js +22 -9
- package/packages/@repo/previewing/src/index.ts +32 -9
- package/packages/@repo/validation/src/blodemd-docs-schema.json +7 -1
package/docs/app/globals.css
CHANGED
|
@@ -347,7 +347,7 @@
|
|
|
347
347
|
border-color: var(--border);
|
|
348
348
|
border-width: 0px;
|
|
349
349
|
border-radius: var(--radius-xl);
|
|
350
|
-
@apply
|
|
350
|
+
@apply md:-mx-1;
|
|
351
351
|
|
|
352
352
|
&:has([data-rehype-pretty-code-title]) [data-slot="copy-button"] {
|
|
353
353
|
top: calc(var(--spacing) * 1.5) !important;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type * as React from "react";
|
|
4
|
+
|
|
5
|
+
type ButtonProps = React.ComponentProps<"button">;
|
|
6
|
+
|
|
7
|
+
const Button = ({ children, ...props }: ButtonProps) => (
|
|
8
|
+
<button type="button" {...props}>
|
|
9
|
+
{children}
|
|
10
|
+
</button>
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
export { Button };
|
|
14
|
+
export type { ButtonProps };
|
|
@@ -203,9 +203,25 @@ export const CopyPageMenu = ({
|
|
|
203
203
|
|
|
204
204
|
const handleCopy = useCallback(async () => {
|
|
205
205
|
try {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
// iOS Safari loses the user gesture context after any async gap (e.g. a
|
|
207
|
+
// fetch). To keep clipboard access working, we call clipboard.write()
|
|
208
|
+
// synchronously within the gesture and pass a Promise to ClipboardItem
|
|
209
|
+
// so the content resolves later while the gesture context stays alive.
|
|
210
|
+
const blobPromise = (async () => {
|
|
211
|
+
const nextContent = await getContent();
|
|
212
|
+
const markdown = formatMarkdownForCopy(nextContent, title);
|
|
213
|
+
return new Blob([markdown], { type: "text/plain" });
|
|
214
|
+
})();
|
|
215
|
+
|
|
216
|
+
if (typeof ClipboardItem === "undefined") {
|
|
217
|
+
const blob = await blobPromise;
|
|
218
|
+
await navigator.clipboard.writeText(await blob.text());
|
|
219
|
+
} else {
|
|
220
|
+
await navigator.clipboard.write([
|
|
221
|
+
new ClipboardItem({ "text/plain": blobPromise }),
|
|
222
|
+
]);
|
|
223
|
+
}
|
|
224
|
+
|
|
209
225
|
setTemporaryCopyStatus("copied");
|
|
210
226
|
closeMenu();
|
|
211
227
|
} catch {
|
|
@@ -185,8 +185,8 @@ export const DocShell = ({
|
|
|
185
185
|
<div className="flex flex-col gap-2">
|
|
186
186
|
<Breadcrumbs basePath={basePath} breadcrumbs={breadcrumbs} />
|
|
187
187
|
<div className="flex flex-col gap-2">
|
|
188
|
-
<div className="flex items-
|
|
189
|
-
<h1 className="scroll-m-24 text-3xl font-semibold tracking-tight sm:text-3xl">
|
|
188
|
+
<div className="flex flex-col items-start gap-3 sm:flex-row sm:justify-between">
|
|
189
|
+
<h1 className="min-w-0 scroll-m-24 text-3xl font-semibold tracking-tight sm:text-3xl">
|
|
190
190
|
{pageTitle}
|
|
191
191
|
{deprecated ? (
|
|
192
192
|
<span className="ml-3 inline-flex translate-y-[-2px] items-center rounded-md bg-yellow-100 px-2 py-0.5 align-middle text-xs font-medium text-yellow-800 dark:bg-yellow-900/40 dark:text-yellow-300">
|
|
@@ -212,7 +212,7 @@ export const DocShell = ({
|
|
|
212
212
|
) : null}
|
|
213
213
|
</div>
|
|
214
214
|
</div>
|
|
215
|
-
<div className="grid gap-4.5 leading-relaxed [&_blockquote]:border-l-3 [&_blockquote]:border-primary [&_blockquote]:pl-3.5 [&_blockquote]:text-muted-foreground [&_h2]:mt-10 [&_h2]:mb-3 [&_h2]:text-2xl [&_h2]:font-bold [&_h3]:mt-8 [&_h3]:mb-2 [&_h3]:text-[1.375rem] [&_h3]:font-semibold [&_h4]:mt-6 [&_h4]:mb-2 [&_h4]:text-base [&_h4]:font-semibold [&_ol]:list-decimal [&_ol]:pl-
|
|
215
|
+
<div className="grid min-w-0 grid-cols-1 gap-4.5 leading-relaxed [&_blockquote]:border-l-3 [&_blockquote]:border-primary [&_blockquote]:pl-3.5 [&_blockquote]:text-muted-foreground [&_h2]:mt-10 [&_h2]:mb-3 [&_h2]:text-2xl [&_h2]:font-bold [&_h3]:mt-8 [&_h3]:mb-2 [&_h3]:text-[1.375rem] [&_h3]:font-semibold [&_h4]:mt-6 [&_h4]:mb-2 [&_h4]:text-base [&_h4]:font-semibold [&_ol]:list-decimal [&_ol]:pl-6 [&_table]:w-full [&_table]:border-collapse [&_table]:text-sm [&_td]:border-b [&_td]:border-border [&_td]:px-2.5 [&_td]:py-2 [&_td]:text-left [&_th]:border-b [&_th]:border-border [&_th]:px-2.5 [&_th]:py-2 [&_th]:text-left [&_ul]:list-disc [&_ul]:pl-6">
|
|
216
216
|
{content}
|
|
217
217
|
</div>
|
|
218
218
|
{!hideFooterPagination && (prevPage || nextPage) ? (
|
|
@@ -24,7 +24,7 @@ export const Step = ({
|
|
|
24
24
|
const anchorId = id ?? title.toLowerCase().replaceAll(/\s+/g, "-");
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
|
-
<div className="relative pb-8 pl-10 last:pb-0" id={anchorId}>
|
|
27
|
+
<div className="relative pb-8 pl-8 sm:pl-10 last:pb-0" id={anchorId}>
|
|
28
28
|
<div
|
|
29
29
|
aria-hidden
|
|
30
30
|
className="absolute left-0 flex size-7 items-center justify-center rounded-full border border-border bg-muted font-mono text-xs font-medium"
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Checkmark1Icon as CheckIcon,
|
|
5
|
+
CopySimpleIcon as CopyIcon,
|
|
6
|
+
} from "blode-icons-react";
|
|
7
|
+
import { cva } from "class-variance-authority";
|
|
8
|
+
import type { VariantProps } from "class-variance-authority";
|
|
9
|
+
import { AnimatePresence, motion } from "motion/react";
|
|
10
|
+
import { useCallback } from "react";
|
|
11
|
+
import type { MouseEvent } from "react";
|
|
12
|
+
|
|
13
|
+
import { Button as ButtonPrimitive } from "@/components/animate-ui/primitives/buttons/button";
|
|
14
|
+
import type { ButtonProps as ButtonPrimitiveProps } from "@/components/animate-ui/primitives/buttons/button";
|
|
15
|
+
import { useControlledState } from "@/hooks/use-controlled-state";
|
|
16
|
+
import { cn } from "@/lib/utils";
|
|
17
|
+
|
|
18
|
+
const buttonVariants = cva(
|
|
19
|
+
"flex shrink-0 items-center justify-center rounded-md outline-none transition-[box-shadow,_color,_background-color,_border-color,_outline-color,_text-decoration-color,_fill,_stroke] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
20
|
+
{
|
|
21
|
+
defaultVariants: {
|
|
22
|
+
size: "default",
|
|
23
|
+
variant: "default",
|
|
24
|
+
},
|
|
25
|
+
variants: {
|
|
26
|
+
size: {
|
|
27
|
+
default: "size-9",
|
|
28
|
+
lg: "size-10 rounded-md",
|
|
29
|
+
sm: "size-8 rounded-md",
|
|
30
|
+
xs: "size-7 rounded-md [&_svg:not([class*='size-'])]:size-3.5",
|
|
31
|
+
},
|
|
32
|
+
variant: {
|
|
33
|
+
accent: "bg-accent text-accent-foreground shadow-xs hover:bg-accent/90",
|
|
34
|
+
default:
|
|
35
|
+
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
|
36
|
+
destructive:
|
|
37
|
+
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
|
|
38
|
+
ghost:
|
|
39
|
+
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
40
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
41
|
+
outline:
|
|
42
|
+
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
43
|
+
secondary:
|
|
44
|
+
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
type CopyButtonProps = Omit<ButtonPrimitiveProps, "children"> &
|
|
51
|
+
VariantProps<typeof buttonVariants> & {
|
|
52
|
+
content: string;
|
|
53
|
+
copied?: boolean;
|
|
54
|
+
delay?: number;
|
|
55
|
+
onCopiedChange?: (copied: boolean, content?: string) => void;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const CopyButton = ({
|
|
59
|
+
className,
|
|
60
|
+
content,
|
|
61
|
+
copied,
|
|
62
|
+
onCopiedChange,
|
|
63
|
+
onClick,
|
|
64
|
+
variant,
|
|
65
|
+
size,
|
|
66
|
+
delay = 3000,
|
|
67
|
+
...props
|
|
68
|
+
}: CopyButtonProps) => {
|
|
69
|
+
const [isCopied, setIsCopied] = useControlledState({
|
|
70
|
+
onChange: onCopiedChange,
|
|
71
|
+
value: copied,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const handleCopy = useCallback(
|
|
75
|
+
async (e: MouseEvent<HTMLButtonElement>) => {
|
|
76
|
+
onClick?.(e);
|
|
77
|
+
if (copied) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (content) {
|
|
81
|
+
try {
|
|
82
|
+
await navigator.clipboard.writeText(content);
|
|
83
|
+
setIsCopied(true);
|
|
84
|
+
onCopiedChange?.(true, content);
|
|
85
|
+
setTimeout(() => {
|
|
86
|
+
setIsCopied(false);
|
|
87
|
+
onCopiedChange?.(false);
|
|
88
|
+
}, delay);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error("Error copying command", error);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
[onClick, copied, content, setIsCopied, onCopiedChange, delay]
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<ButtonPrimitive
|
|
101
|
+
className={cn(buttonVariants({ className, size, variant }))}
|
|
102
|
+
data-slot="copy-button"
|
|
103
|
+
onClick={handleCopy}
|
|
104
|
+
{...props}
|
|
105
|
+
>
|
|
106
|
+
<AnimatePresence mode="popLayout">
|
|
107
|
+
<motion.span
|
|
108
|
+
animate={{ filter: "blur(0px)", opacity: 1, scale: 1 }}
|
|
109
|
+
data-slot="copy-button-icon"
|
|
110
|
+
exit={{ filter: "blur(4px)", opacity: 0.4, scale: 0 }}
|
|
111
|
+
initial={false}
|
|
112
|
+
key={isCopied ? "check" : "copy"}
|
|
113
|
+
transition={{ duration: 0.25 }}
|
|
114
|
+
>
|
|
115
|
+
<Icon />
|
|
116
|
+
</motion.span>
|
|
117
|
+
</AnimatePresence>
|
|
118
|
+
</ButtonPrimitive>
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export { CopyButton };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import Image from "next/image";
|
|
2
|
+
|
|
3
|
+
import { siteConfig } from "@/lib/config";
|
|
4
|
+
|
|
5
|
+
export const SiteFooter = () => (
|
|
6
|
+
<footer className="flex flex-col items-center justify-center gap-2 pt-16 pb-8 text-muted-foreground text-sm">
|
|
7
|
+
<div className="flex items-center gap-1">
|
|
8
|
+
Crafted by
|
|
9
|
+
<a
|
|
10
|
+
className="flex items-center gap-2 rounded-full py-1.5 pr-2.5 pl-1.5 transition-colors hover:text-foreground"
|
|
11
|
+
href={siteConfig.links.author}
|
|
12
|
+
rel="noopener noreferrer"
|
|
13
|
+
target="_blank"
|
|
14
|
+
>
|
|
15
|
+
<Image
|
|
16
|
+
alt="Avatar of Matthew Blode"
|
|
17
|
+
className="rounded-full"
|
|
18
|
+
height={20}
|
|
19
|
+
src="/matthew-blode-profile.jpg"
|
|
20
|
+
unoptimized
|
|
21
|
+
width={20}
|
|
22
|
+
/>
|
|
23
|
+
Matthew Blode
|
|
24
|
+
</a>
|
|
25
|
+
</div>
|
|
26
|
+
<div className="flex items-center gap-2 text-muted-foreground/30">
|
|
27
|
+
<span className="text-muted-foreground">v{siteConfig.version}</span>{" "}
|
|
28
|
+
•
|
|
29
|
+
<a
|
|
30
|
+
className="text-muted-foreground transition-colors hover:text-foreground"
|
|
31
|
+
href={siteConfig.links.github}
|
|
32
|
+
rel="noopener noreferrer"
|
|
33
|
+
target="_blank"
|
|
34
|
+
>
|
|
35
|
+
GitHub
|
|
36
|
+
</a>
|
|
37
|
+
</div>
|
|
38
|
+
</footer>
|
|
39
|
+
);
|
package/docs/lib/tenancy.ts
CHANGED
|
@@ -15,22 +15,47 @@ const DEFAULT_RESERVED_PATHS = [
|
|
|
15
15
|
"/_internal",
|
|
16
16
|
"/_next",
|
|
17
17
|
"/.well-known",
|
|
18
|
+
"/api",
|
|
18
19
|
"/docs.json",
|
|
19
20
|
"/favicon.ico",
|
|
20
21
|
"/llms.txt",
|
|
22
|
+
"/logos",
|
|
21
23
|
"/oauth",
|
|
22
24
|
"/robots.txt",
|
|
23
25
|
"/sitemap.xml",
|
|
24
|
-
"/logos",
|
|
25
|
-
"/file-text.svg",
|
|
26
|
-
"/globe.svg",
|
|
27
|
-
"/next.svg",
|
|
28
|
-
"/turborepo-dark.svg",
|
|
29
|
-
"/turborepo-light.svg",
|
|
30
|
-
"/vercel.svg",
|
|
31
|
-
"/window.svg",
|
|
32
26
|
];
|
|
33
27
|
|
|
28
|
+
const STATIC_ASSET_EXTENSIONS = new Set([
|
|
29
|
+
".avif",
|
|
30
|
+
".css",
|
|
31
|
+
".eot",
|
|
32
|
+
".gif",
|
|
33
|
+
".ico",
|
|
34
|
+
".jpeg",
|
|
35
|
+
".jpg",
|
|
36
|
+
".js",
|
|
37
|
+
".json",
|
|
38
|
+
".map",
|
|
39
|
+
".png",
|
|
40
|
+
".svg",
|
|
41
|
+
".ttf",
|
|
42
|
+
".webp",
|
|
43
|
+
".woff",
|
|
44
|
+
".woff2",
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
const isRootStaticAsset = (pathname: string): boolean => {
|
|
48
|
+
const segments = pathname.split("/").filter(Boolean);
|
|
49
|
+
if (segments.length !== 1) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const lastDot = pathname.lastIndexOf(".");
|
|
53
|
+
if (lastDot === -1) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return STATIC_ASSET_EXTENSIONS.has(pathname.slice(lastDot).toLowerCase());
|
|
57
|
+
};
|
|
58
|
+
|
|
34
59
|
const LOCAL_ROOT_HOSTS = new Set(["localhost", "127.0.0.1"]);
|
|
35
60
|
const TRAILING_SLASHES_REGEX = /\/+$/;
|
|
36
61
|
const LEADING_SLASHES_REGEX = /^\/+/;
|
|
@@ -105,6 +130,9 @@ export const isReservedPath = (pathname: string) => {
|
|
|
105
130
|
if (assetPrefix && pathname.startsWith(assetPrefix)) {
|
|
106
131
|
return true;
|
|
107
132
|
}
|
|
133
|
+
if (isRootStaticAsset(pathname)) {
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
108
136
|
return DEFAULT_RESERVED_PATHS.some((prefix) => pathname.startsWith(prefix));
|
|
109
137
|
};
|
|
110
138
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blodemd",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"description": "Blode.md CLI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"@base-ui/react": "^1.3.0",
|
|
41
41
|
"@clack/prompts": "^1.0.0",
|
|
42
42
|
"@mdx-js/mdx": "^3.1.1",
|
|
43
|
-
"@repo/common": "*",
|
|
44
43
|
"@shikijs/rehype": "^4.0.2",
|
|
45
44
|
"@tailwindcss/postcss": "^4.2.2",
|
|
46
45
|
"@types/node": "^22.19.15",
|
|
@@ -74,6 +73,7 @@
|
|
|
74
73
|
"zod": "^4.3.6"
|
|
75
74
|
},
|
|
76
75
|
"devDependencies": {
|
|
76
|
+
"@repo/common": "*",
|
|
77
77
|
"@repo/previewing": "*",
|
|
78
78
|
"@repo/typescript-config": "*",
|
|
79
79
|
"oxfmt": "^0.42.0",
|
|
@@ -443,6 +443,7 @@ export declare const DocsConfigSchema: z.ZodObject<{
|
|
|
443
443
|
all: "all";
|
|
444
444
|
}>>;
|
|
445
445
|
}, z.core.$strict>>;
|
|
446
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
446
447
|
}, z.core.$strict>;
|
|
447
448
|
export type DocsConfig = z.infer<typeof DocsConfigSchema>;
|
|
448
449
|
export declare const MintlifyDocsConfigSchema: z.ZodObject<{
|
|
@@ -639,6 +640,7 @@ export declare const MintlifyDocsConfigSchema: z.ZodObject<{
|
|
|
639
640
|
all: "all";
|
|
640
641
|
}>>;
|
|
641
642
|
}, z.core.$strict>>;
|
|
643
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
642
644
|
}, z.core.$strict>;
|
|
643
645
|
export type MintlifyDocsConfig = DocsConfig;
|
|
644
646
|
export declare const ContentTypeSchema: z.ZodEnum<{
|
|
@@ -1138,6 +1140,7 @@ export declare const SiteConfigSchema: z.ZodObject<{
|
|
|
1138
1140
|
all: "all";
|
|
1139
1141
|
}>>;
|
|
1140
1142
|
}, z.core.$strict>>;
|
|
1143
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
1141
1144
|
theme: z.ZodOptional<z.ZodString>;
|
|
1142
1145
|
}, z.core.$strict>;
|
|
1143
1146
|
export type SiteConfig = z.infer<typeof SiteConfigSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-config.d.ts","sourceRoot":"","sources":["../src/docs-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"docs-config.d.ts","sourceRoot":"","sources":["../src/docs-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
const UrlOrPathSchema = z.string().min(1);
|
|
3
|
+
const SlugSchema = z
|
|
4
|
+
.string()
|
|
5
|
+
.min(1)
|
|
6
|
+
.regex(/^[a-z0-9-]+$/);
|
|
3
7
|
export const DocsColorsSchema = z
|
|
4
8
|
.object({
|
|
5
9
|
background: z.string().optional(),
|
|
@@ -370,6 +374,7 @@ export const DocsConfigSchema = z
|
|
|
370
374
|
navigation: MintlifyNavigationSchema,
|
|
371
375
|
search: MintlifySearchSchema.optional(),
|
|
372
376
|
seo: DocsSeoSchema.optional(),
|
|
377
|
+
slug: SlugSchema.optional(),
|
|
373
378
|
})
|
|
374
379
|
.strict();
|
|
375
380
|
export const MintlifyDocsConfigSchema = DocsConfigSchema;
|
|
@@ -518,6 +523,7 @@ export const SiteConfigSchema = z
|
|
|
518
523
|
openapiProxy: DocsOpenApiProxySchema.optional(),
|
|
519
524
|
scripts: DocsScriptsSchema.optional(),
|
|
520
525
|
seo: DocsSeoSchema.optional(),
|
|
526
|
+
slug: SlugSchema.optional(),
|
|
521
527
|
theme: z.string().optional(),
|
|
522
528
|
})
|
|
523
529
|
.strict();
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
3
|
const UrlOrPathSchema = z.string().min(1);
|
|
4
|
+
const SlugSchema = z
|
|
5
|
+
.string()
|
|
6
|
+
.min(1)
|
|
7
|
+
.regex(/^[a-z0-9-]+$/);
|
|
4
8
|
|
|
5
9
|
export const DocsColorsSchema = z
|
|
6
10
|
.object({
|
|
@@ -432,6 +436,7 @@ export const DocsConfigSchema = z
|
|
|
432
436
|
navigation: MintlifyNavigationSchema,
|
|
433
437
|
search: MintlifySearchSchema.optional(),
|
|
434
438
|
seo: DocsSeoSchema.optional(),
|
|
439
|
+
slug: SlugSchema.optional(),
|
|
435
440
|
})
|
|
436
441
|
.strict();
|
|
437
442
|
|
|
@@ -610,6 +615,7 @@ export const SiteConfigSchema = z
|
|
|
610
615
|
openapiProxy: DocsOpenApiProxySchema.optional(),
|
|
611
616
|
scripts: DocsScriptsSchema.optional(),
|
|
612
617
|
seo: DocsSeoSchema.optional(),
|
|
618
|
+
slug: SlugSchema.optional(),
|
|
613
619
|
theme: z.string().optional(),
|
|
614
620
|
})
|
|
615
621
|
.strict();
|
|
@@ -13,6 +13,7 @@ export declare const PREBUILT_UTILITY_SITEMAP_PATH = "_utility/sitemap.xml";
|
|
|
13
13
|
export declare const PREBUILT_UTILITY_LLMS_PATH = "_utility/llms.txt";
|
|
14
14
|
export declare const PREBUILT_UTILITY_LLMS_FULL_PATH = "_utility/llms-full.txt";
|
|
15
15
|
export declare const UTILITY_DOCS_ROOT_TOKEN = "__BLODEMD_DOCS_ROOT__";
|
|
16
|
+
export declare const LEGACY_PROJECT_NAME_FALLBACK_WARNING = "docs.json.slug is recommended. Falling back to docs.json.name as the deployment slug is deprecated.";
|
|
16
17
|
export type SiteConfigResult = {
|
|
17
18
|
ok: true;
|
|
18
19
|
config: SiteConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,WAAW,EAEX,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACX,MAAM,cAAc,CAAC;AAQtB,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,WAAW,EAEX,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACX,MAAM,cAAc,CAAC;AAQtB,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAQpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAE5E,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AACzD,eAAO,MAAM,2BAA2B,wBAAwB,CAAC;AACjE,eAAO,MAAM,0BAA0B,uBAAuB,CAAC;AAC/D,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AACzD,eAAO,MAAM,2BAA2B,wBAAwB,CAAC;AACjE,eAAO,MAAM,6BAA6B,yBAAyB,CAAC;AACpE,eAAO,MAAM,0BAA0B,sBAAsB,CAAC;AAC9D,eAAO,MAAM,+BAA+B,2BAA2B,CAAC;AACxE,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAC/D,eAAO,MAAM,oCAAoC,wGACsD,CAAC;AAExG,MAAM,MAAM,gBAAgB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,GACpD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEpC,MAAM,MAAM,YAAY,GACpB;IACE,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,iBAAiB,CAAC,WAAW,CAAC,CAAC;CAC7C,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEN,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAClC,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;IAC1C,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,iBAAiB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;CACnB;AAID,eAAO,MAAM,oBAAoB,GAC/B,OAAO,YAAY,KAClB,GAAG,CAAC,MAAM,EAAE,YAAY,CAoD1B,CAAC;AAoTF,eAAO,MAAM,cAAc,GACzB,QAAQ,aAAa,KACpB,OAAO,CAAC,gBAAgB,CAU1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,aAAa,EACrB,cAAc,MAAM,oBACkB,CAAC;AAyLzC,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,aAAa,EACrB,QAAQ,UAAU,KACjB,OAAO,CAAC,YAAY,CAkFtB,CAAC;AAuCF,eAAO,MAAM,UAAU,GAAI,QAAQ,MAAM,KAAG,OAAO,EAwBlD,CAAC;AAiBF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,EAAE,QAAQ,MAAM,WAO/D,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,OAAO,MAAM,EACb,KAAK,MAAM,EACX,QAAQ,MAAM,WAQf,CAAC;AA2QF,eAAO,MAAM,gBAAgB,GAC3B,OAAO,YAAY,EACnB,QAAQ,UAAU,EAClB,eAAe,YAAY,KAC1B,eAAe,EAyBjB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,OAAO,YAAY,EACnB,QAAQ,aAAa,EACrB,QAAQ,UAAU,KACjB,OAAO,CAAC,YAAY,CAuCtB,CAAC;AAaF,eAAO,MAAM,6BAA6B,GAAI,MAAM,MAAM,WAGzD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,OAAO,YAAY,KAClB,eAAe,EAuDjB,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,OAAO,YAAY,EACnB,QAAQ,aAAa,KACpB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAahC,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,OAAO,YAAY,KAAG,MAKvB,CAAC;AAEtC,eAAO,MAAM,qBAAqB,GAChC,SAAS,oBAAoB,EAAE,KAC9B,MAIkC,CAAC;AAEtC,eAAO,MAAM,wBAAwB,GACnC,QAAQ,aAAa,KACpB,OAAO,CAAC,YAAY,GAAG,IAAI,CA8B7B,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,QAAQ,aAAa,KACpB,OAAO,CAAC,oBAAoB,EAAE,GAAG,IAAI,CAYvC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,eAAe,EAAE,KAAG,MAI5B,CAAC;AAErC,eAAO,MAAM,uBAAuB,GAClC,QAAQ,aAAa,KACpB,OAAO,CAAC,eAAe,EAAE,GAAG,IAAI,CAYlC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,aAAa,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,KAClC,MAI8B,CAAC;AAElC,eAAO,MAAM,oBAAoB,GAC/B,QAAQ,aAAa,KACpB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,CAYvC,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,OAAO,YAAY,KAAG,MAIvB,CAAC;AAEtC,eAAO,MAAM,wBAAwB,GACnC,QAAQ,aAAa,KACpB,OAAO,CAAC,YAAY,GAAG,IAAI,CAoB7B,CAAC"}
|
|
@@ -2,7 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { ensureArray, normalizePath, slugify } from "@repo/common";
|
|
3
3
|
import { PageModeSchema } from "@repo/models";
|
|
4
4
|
import { extractOpenApiOperations, openApiIdentifier, openApiSlug, parseOpenApiSpec, } from "@repo/prebuild";
|
|
5
|
-
import { validateDocsConfig, validateFrontmatter } from "@repo/validation";
|
|
5
|
+
import { validateDocsConfig, validateFrontmatter, validateSiteConfig, } from "@repo/validation";
|
|
6
6
|
import YAML from "yaml";
|
|
7
7
|
export { BlobContentSource, createBlobSource } from "./blob-source.js";
|
|
8
8
|
export { createFsSource, FsContentSource } from "./fs-source.js";
|
|
@@ -15,6 +15,7 @@ export const PREBUILT_UTILITY_SITEMAP_PATH = "_utility/sitemap.xml";
|
|
|
15
15
|
export const PREBUILT_UTILITY_LLMS_PATH = "_utility/llms.txt";
|
|
16
16
|
export const PREBUILT_UTILITY_LLMS_FULL_PATH = "_utility/llms-full.txt";
|
|
17
17
|
export const UTILITY_DOCS_ROOT_TOKEN = "__BLODEMD_DOCS_ROOT__";
|
|
18
|
+
export const LEGACY_PROJECT_NAME_FALLBACK_WARNING = "docs.json.slug is recommended. Falling back to docs.json.name as the deployment slug is deprecated.";
|
|
18
19
|
const validModes = new Set(PageModeSchema.options);
|
|
19
20
|
export const buildPageMetadataMap = (index) => {
|
|
20
21
|
const map = new Map();
|
|
@@ -203,8 +204,10 @@ const mapDocsConfig = (docs) => {
|
|
|
203
204
|
Boolean(docs.api?.openapi || docs.api?.asyncapi),
|
|
204
205
|
},
|
|
205
206
|
seo: docs.seo,
|
|
207
|
+
slug: docs.slug,
|
|
206
208
|
};
|
|
207
209
|
};
|
|
210
|
+
const getProjectWarnings = (config) => config.slug ? [] : [LEGACY_PROJECT_NAME_FALLBACK_WARNING];
|
|
208
211
|
const readJsonConfig = async (source, relativePath) => JSON.parse(await source.readFile(relativePath));
|
|
209
212
|
const normalizeRefPath = (baseDirectory, reference) => {
|
|
210
213
|
if (reference.startsWith("/") ||
|
|
@@ -271,15 +274,25 @@ const loadDocsConfig = async (source) => {
|
|
|
271
274
|
}
|
|
272
275
|
try {
|
|
273
276
|
const parsed = await readResolvedJsonConfig(source, DOCS_CONFIG_FILE);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
+
// Try SiteConfig format first (has collections, theme, colors, etc.)
|
|
278
|
+
const siteResult = validateSiteConfig(parsed);
|
|
279
|
+
if (siteResult.success) {
|
|
280
|
+
return {
|
|
281
|
+
config: siteResult.data,
|
|
282
|
+
ok: true,
|
|
283
|
+
warnings: getProjectWarnings(siteResult.data),
|
|
284
|
+
};
|
|
277
285
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
286
|
+
// Fall back to DocsConfig format (Mintlify-compatible) and map to SiteConfig
|
|
287
|
+
const docsResult = validateDocsConfig(parsed);
|
|
288
|
+
if (docsResult.success) {
|
|
289
|
+
return {
|
|
290
|
+
config: mapDocsConfig(docsResult.data),
|
|
291
|
+
ok: true,
|
|
292
|
+
warnings: getProjectWarnings(docsResult.data),
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
return { errors: docsResult.errors, ok: false };
|
|
283
296
|
}
|
|
284
297
|
catch (error) {
|
|
285
298
|
return {
|
|
@@ -18,7 +18,11 @@ import {
|
|
|
18
18
|
parseOpenApiSpec,
|
|
19
19
|
} from "@repo/prebuild";
|
|
20
20
|
import type { OpenApiOperation, OpenApiSpec } from "@repo/prebuild";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
validateDocsConfig,
|
|
23
|
+
validateFrontmatter,
|
|
24
|
+
validateSiteConfig,
|
|
25
|
+
} from "@repo/validation";
|
|
22
26
|
import YAML from "yaml";
|
|
23
27
|
|
|
24
28
|
import type { ContentSource } from "./content-source.js";
|
|
@@ -36,6 +40,8 @@ export const PREBUILT_UTILITY_SITEMAP_PATH = "_utility/sitemap.xml";
|
|
|
36
40
|
export const PREBUILT_UTILITY_LLMS_PATH = "_utility/llms.txt";
|
|
37
41
|
export const PREBUILT_UTILITY_LLMS_FULL_PATH = "_utility/llms-full.txt";
|
|
38
42
|
export const UTILITY_DOCS_ROOT_TOKEN = "__BLODEMD_DOCS_ROOT__";
|
|
43
|
+
export const LEGACY_PROJECT_NAME_FALLBACK_WARNING =
|
|
44
|
+
"docs.json.slug is recommended. Falling back to docs.json.name as the deployment slug is deprecated.";
|
|
39
45
|
|
|
40
46
|
export type SiteConfigResult =
|
|
41
47
|
| { ok: true; config: SiteConfig; warnings: string[] }
|
|
@@ -330,9 +336,13 @@ const mapDocsConfig = (docs: DocsConfig): SiteConfig => {
|
|
|
330
336
|
Boolean(docs.api?.openapi || docs.api?.asyncapi),
|
|
331
337
|
},
|
|
332
338
|
seo: docs.seo,
|
|
339
|
+
slug: docs.slug,
|
|
333
340
|
};
|
|
334
341
|
};
|
|
335
342
|
|
|
343
|
+
const getProjectWarnings = (config: { slug?: string }): string[] =>
|
|
344
|
+
config.slug ? [] : [LEGACY_PROJECT_NAME_FALLBACK_WARNING];
|
|
345
|
+
|
|
336
346
|
const readJsonConfig = async (source: ContentSource, relativePath: string) =>
|
|
337
347
|
JSON.parse(await source.readFile(relativePath)) as unknown;
|
|
338
348
|
|
|
@@ -452,15 +462,28 @@ const loadDocsConfig = async (
|
|
|
452
462
|
|
|
453
463
|
try {
|
|
454
464
|
const parsed = await readResolvedJsonConfig(source, DOCS_CONFIG_FILE);
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
465
|
+
|
|
466
|
+
// Try SiteConfig format first (has collections, theme, colors, etc.)
|
|
467
|
+
const siteResult = validateSiteConfig(parsed);
|
|
468
|
+
if (siteResult.success) {
|
|
469
|
+
return {
|
|
470
|
+
config: siteResult.data,
|
|
471
|
+
ok: true,
|
|
472
|
+
warnings: getProjectWarnings(siteResult.data),
|
|
473
|
+
};
|
|
458
474
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
475
|
+
|
|
476
|
+
// Fall back to DocsConfig format (Mintlify-compatible) and map to SiteConfig
|
|
477
|
+
const docsResult = validateDocsConfig(parsed);
|
|
478
|
+
if (docsResult.success) {
|
|
479
|
+
return {
|
|
480
|
+
config: mapDocsConfig(docsResult.data),
|
|
481
|
+
ok: true,
|
|
482
|
+
warnings: getProjectWarnings(docsResult.data),
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
return { errors: docsResult.errors, ok: false };
|
|
464
487
|
} catch (error) {
|
|
465
488
|
return {
|
|
466
489
|
errors: [
|
|
@@ -3233,7 +3233,7 @@
|
|
|
3233
3233
|
"name": {
|
|
3234
3234
|
"type": "string",
|
|
3235
3235
|
"minLength": 1,
|
|
3236
|
-
"description": "
|
|
3236
|
+
"description": "Display name for your site, project, or organization."
|
|
3237
3237
|
},
|
|
3238
3238
|
"description": {
|
|
3239
3239
|
"type": "string",
|
|
@@ -3561,6 +3561,12 @@
|
|
|
3561
3561
|
},
|
|
3562
3562
|
"additionalProperties": false,
|
|
3563
3563
|
"description": "Metadata configuration for documentation pages"
|
|
3564
|
+
},
|
|
3565
|
+
"slug": {
|
|
3566
|
+
"description": "URL-safe project slug used for deployments and the default `{slug}.blode.md` hostname.",
|
|
3567
|
+
"minLength": 1,
|
|
3568
|
+
"pattern": "^[a-z0-9-]+$",
|
|
3569
|
+
"type": "string"
|
|
3564
3570
|
}
|
|
3565
3571
|
},
|
|
3566
3572
|
"required": ["name", "navigation"],
|