blodemd 0.0.9 → 0.0.10
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/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 +1 -1
- package/packages/@repo/previewing/dist/index.d.ts.map +1 -1
- package/packages/@repo/previewing/dist/index.js +19 -9
- package/packages/@repo/previewing/src/index.ts +26 -9
|
Binary file
|
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 +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":"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"}
|
|
@@ -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";
|
|
@@ -271,15 +271,25 @@ const loadDocsConfig = async (source) => {
|
|
|
271
271
|
}
|
|
272
272
|
try {
|
|
273
273
|
const parsed = await readResolvedJsonConfig(source, DOCS_CONFIG_FILE);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
274
|
+
// Try SiteConfig format first (has collections, theme, colors, etc.)
|
|
275
|
+
const siteResult = validateSiteConfig(parsed);
|
|
276
|
+
if (siteResult.success) {
|
|
277
|
+
return {
|
|
278
|
+
config: siteResult.data,
|
|
279
|
+
ok: true,
|
|
280
|
+
warnings: [],
|
|
281
|
+
};
|
|
277
282
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
+
// Fall back to DocsConfig format (Mintlify-compatible) and map to SiteConfig
|
|
284
|
+
const docsResult = validateDocsConfig(parsed);
|
|
285
|
+
if (docsResult.success) {
|
|
286
|
+
return {
|
|
287
|
+
config: mapDocsConfig(docsResult.data),
|
|
288
|
+
ok: true,
|
|
289
|
+
warnings: [],
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
return { errors: docsResult.errors, ok: false };
|
|
283
293
|
}
|
|
284
294
|
catch (error) {
|
|
285
295
|
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";
|
|
@@ -452,15 +456,28 @@ const loadDocsConfig = async (
|
|
|
452
456
|
|
|
453
457
|
try {
|
|
454
458
|
const parsed = await readResolvedJsonConfig(source, DOCS_CONFIG_FILE);
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
459
|
+
|
|
460
|
+
// Try SiteConfig format first (has collections, theme, colors, etc.)
|
|
461
|
+
const siteResult = validateSiteConfig(parsed);
|
|
462
|
+
if (siteResult.success) {
|
|
463
|
+
return {
|
|
464
|
+
config: siteResult.data,
|
|
465
|
+
ok: true,
|
|
466
|
+
warnings: [],
|
|
467
|
+
};
|
|
458
468
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
469
|
+
|
|
470
|
+
// Fall back to DocsConfig format (Mintlify-compatible) and map to SiteConfig
|
|
471
|
+
const docsResult = validateDocsConfig(parsed);
|
|
472
|
+
if (docsResult.success) {
|
|
473
|
+
return {
|
|
474
|
+
config: mapDocsConfig(docsResult.data),
|
|
475
|
+
ok: true,
|
|
476
|
+
warnings: [],
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return { errors: docsResult.errors, ok: false };
|
|
464
481
|
} catch (error) {
|
|
465
482
|
return {
|
|
466
483
|
errors: [
|