blodemd 0.0.6 → 0.0.7

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.
Files changed (34) hide show
  1. package/README.md +2 -2
  2. package/dev-server/app/favicon.ico +0 -0
  3. package/dev-server/next-env.d.ts +5 -0
  4. package/dev-server/package.json +1 -1
  5. package/dev-server/tsconfig.json +3 -2
  6. package/dist/cli.mjs +209 -53
  7. package/dist/cli.mjs.map +1 -1
  8. package/docs/app/globals.css +4 -2
  9. package/docs/components/docs/doc-header.tsx +35 -17
  10. package/docs/components/docs/doc-shell.tsx +46 -22
  11. package/docs/components/docs/doc-sidebar.tsx +13 -8
  12. package/docs/components/docs/mobile-nav.tsx +150 -152
  13. package/docs/components/icons/doc-icon.tsx +96 -0
  14. package/docs/components/mdx/card.tsx +60 -54
  15. package/docs/components/mdx/icon.tsx +2 -46
  16. package/docs/components/mdx/index.tsx +12 -1
  17. package/docs/components/mdx/tree.tsx +7 -7
  18. package/docs/components/ui/search.tsx +11 -7
  19. package/docs/lib/mdx.ts +2 -5
  20. package/docs/lib/navigation.ts +2 -2
  21. package/docs/lib/routes.ts +34 -0
  22. package/docs/lib/shiki.ts +6 -1
  23. package/package.json +13 -5
  24. package/packages/@repo/contracts/dist/tenant.d.ts +12 -0
  25. package/packages/@repo/contracts/dist/tenant.d.ts.map +1 -1
  26. package/packages/@repo/contracts/dist/tenant.js +20 -0
  27. package/packages/@repo/contracts/src/tenant.ts +38 -0
  28. package/packages/@repo/previewing/dist/fs-source.d.ts.map +1 -1
  29. package/packages/@repo/previewing/dist/fs-source.js +1 -8
  30. package/packages/@repo/previewing/src/fs-source.ts +1 -8
  31. package/packages/@repo/validation/src/mintlify-docs-schema.json +1 -1
  32. package/scripts/prepare-package.mjs +39 -0
  33. package/packages/@repo/common/src/common.unit.test.ts +0 -55
  34. package/packages/@repo/previewing/src/index.unit.test.ts +0 -290
@@ -2,6 +2,7 @@ import Image from "next/image";
2
2
  import Link from "next/link";
3
3
  import type { ReactNode } from "react";
4
4
 
5
+ import { DocIcon } from "@/components/icons/doc-icon";
5
6
  import { cn } from "@/lib/utils";
6
7
 
7
8
  interface CardProps {
@@ -24,65 +25,70 @@ const CardInner = ({
24
25
  cta,
25
26
  href,
26
27
  children,
27
- }: CardProps) => (
28
- <div
29
- className={cn(
30
- "group/card rounded-xl border border-border bg-card p-4 transition-colors",
31
- href && "hover:border-primary/30 hover:bg-accent/50",
32
- horizontal && "flex items-start gap-4"
33
- )}
34
- >
35
- {img && !horizontal ? (
36
- <div className="relative mb-3 aspect-video overflow-hidden rounded-lg">
37
- <Image
38
- alt={title ?? ""}
39
- className="object-cover"
40
- fill
41
- sizes="(max-width: 768px) 100vw, 50vw"
42
- src={img}
43
- unoptimized
44
- />
45
- </div>
46
- ) : null}
47
- {icon ? (
48
- <div
49
- className="mb-3 flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground"
50
- style={color ? { color } : undefined}
51
- >
52
- {icon}
53
- </div>
54
- ) : null}
55
- <div className="min-w-0 flex-1">
56
- {title ? (
57
- <div className="mb-1 font-medium text-foreground">{title}</div>
28
+ }: CardProps) => {
29
+ const resolvedIcon =
30
+ typeof icon === "string" ? <DocIcon icon={icon} size={18} /> : icon;
31
+
32
+ return (
33
+ <div
34
+ className={cn(
35
+ "group/card rounded-xl border border-border bg-card p-4 transition-colors",
36
+ href && "hover:border-primary/30 hover:bg-accent/50",
37
+ horizontal && "flex items-start gap-4"
38
+ )}
39
+ >
40
+ {img && !horizontal ? (
41
+ <div className="relative mb-3 aspect-video overflow-hidden rounded-lg">
42
+ <Image
43
+ alt={title ?? ""}
44
+ className="object-cover"
45
+ fill
46
+ sizes="(max-width: 768px) 100vw, 50vw"
47
+ src={img}
48
+ unoptimized
49
+ />
50
+ </div>
58
51
  ) : null}
59
- {children ? (
60
- <div className="text-sm text-muted-foreground [&>p:first-child]:mt-0 [&>p:last-child]:mb-0">
61
- {children}
52
+ {resolvedIcon ? (
53
+ <div
54
+ className="mb-3 flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground"
55
+ style={color ? { color } : undefined}
56
+ >
57
+ {resolvedIcon}
62
58
  </div>
63
59
  ) : null}
64
- {cta ? (
65
- <div className="mt-2 text-sm font-medium text-primary">{cta}</div>
60
+ <div className="min-w-0 flex-1">
61
+ {title ? (
62
+ <div className="mb-1 font-medium text-foreground">{title}</div>
63
+ ) : null}
64
+ {children ? (
65
+ <div className="text-sm text-muted-foreground [&>p:first-child]:mt-0 [&>p:last-child]:mb-0">
66
+ {children}
67
+ </div>
68
+ ) : null}
69
+ {cta ? (
70
+ <div className="mt-2 text-sm font-medium text-primary">{cta}</div>
71
+ ) : null}
72
+ </div>
73
+ {href ? (
74
+ <svg
75
+ aria-hidden
76
+ className="mt-0.5 size-4 shrink-0 text-muted-foreground transition-transform group-hover/card:translate-x-0.5"
77
+ fill="none"
78
+ stroke="currentColor"
79
+ strokeWidth={2}
80
+ viewBox="0 0 24 24"
81
+ >
82
+ <path
83
+ d="M5 12h14M12 5l7 7-7 7"
84
+ strokeLinecap="round"
85
+ strokeLinejoin="round"
86
+ />
87
+ </svg>
66
88
  ) : null}
67
89
  </div>
68
- {href ? (
69
- <svg
70
- aria-hidden
71
- className="mt-0.5 size-4 shrink-0 text-muted-foreground transition-transform group-hover/card:translate-x-0.5"
72
- fill="none"
73
- stroke="currentColor"
74
- strokeWidth={2}
75
- viewBox="0 0 24 24"
76
- >
77
- <path
78
- d="M5 12h14M12 5l7 7-7 7"
79
- strokeLinecap="round"
80
- strokeLinejoin="round"
81
- />
82
- </svg>
83
- ) : null}
84
- </div>
85
- );
90
+ );
91
+ };
86
92
 
87
93
  export const Card = (props: CardProps) => {
88
94
  if (props.href) {
@@ -1,4 +1,4 @@
1
- import { cn } from "@/lib/utils";
1
+ import { DocIcon } from "@/components/icons/doc-icon";
2
2
 
3
3
  interface IconProps {
4
4
  icon: string;
@@ -8,49 +8,5 @@ interface IconProps {
8
8
  }
9
9
 
10
10
  export const Icon = ({ icon, color, size = 16, className }: IconProps) => (
11
- <span
12
- aria-hidden
13
- className={cn("inline-flex items-center justify-center", className)}
14
- style={{
15
- color: color ?? undefined,
16
- height: size,
17
- width: size,
18
- }}
19
- >
20
- <svg
21
- className="size-full"
22
- fill="none"
23
- stroke="currentColor"
24
- strokeLinecap="round"
25
- strokeLinejoin="round"
26
- strokeWidth={2}
27
- viewBox="0 0 24 24"
28
- >
29
- <title>{icon}</title>
30
- {icon === "flag" && (
31
- <path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1zM4 22v-7" />
32
- )}
33
- {icon === "check" && <path d="M20 6 9 17l-5-5" />}
34
- {icon === "star" && (
35
- <path d="m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z" />
36
- )}
37
- {icon === "info" && (
38
- <>
39
- <circle cx="12" cy="12" r="10" />
40
- <path d="M12 16v-4M12 8h.01" />
41
- </>
42
- )}
43
- {icon === "alert-triangle" && (
44
- <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3M12 9v4M12 17h.01" />
45
- )}
46
- {icon === "arrow-right" && <path d="M5 12h14M12 5l7 7-7 7" />}
47
- {icon === "external-link" && (
48
- <>
49
- <path d="M15 3h6v6" />
50
- <path d="M10 14 21 3" />
51
- <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
52
- </>
53
- )}
54
- </svg>
55
- </span>
11
+ <DocIcon className={className} color={color} icon={icon} size={size} />
56
12
  );
@@ -1,5 +1,6 @@
1
1
  import type { MDXComponents } from "mdx/types";
2
2
  import Link from "next/link";
3
+ import type { ComponentProps } from "react";
3
4
 
4
5
  import { Accordion, AccordionGroup } from "./accordion";
5
6
  import { Badge } from "./badge";
@@ -23,12 +24,22 @@ import { Step, Steps } from "./steps";
23
24
  import { Tab, Tabs } from "./tabs";
24
25
  import { Tile } from "./tile";
25
26
  import { Tooltip } from "./tooltip";
26
- import { Tree } from "./tree";
27
+ import { Tree as TreeRoot, TreeFile, TreeFolder } from "./tree";
27
28
  import { TypeTable } from "./type-table";
28
29
  import { Update } from "./update";
29
30
  import { Video } from "./video";
30
31
  import { View, ViewGroup } from "./view";
31
32
 
33
+ // Rebuild dotted MDX exports in the server module so Next's client references
34
+ // still expose `Tree.Folder` and `Tree.File` during MDX evaluation.
35
+ const Tree = Object.assign(
36
+ (props: ComponentProps<typeof TreeRoot>) => <TreeRoot {...props} />,
37
+ {
38
+ File: TreeFile,
39
+ Folder: TreeFolder,
40
+ }
41
+ );
42
+
32
43
  const MdxLink = ({
33
44
  href,
34
45
  children,
@@ -9,7 +9,7 @@ interface TreeFileProps {
9
9
  name: string;
10
10
  }
11
11
 
12
- const TreeFile = ({ name }: TreeFileProps) => (
12
+ export const TreeFile = ({ name }: TreeFileProps) => (
13
13
  <div className="flex items-center gap-2 py-0.5 pl-5 text-sm">
14
14
  <svg
15
15
  aria-hidden
@@ -41,7 +41,7 @@ interface TreeFolderProps {
41
41
  children?: ReactNode;
42
42
  }
43
43
 
44
- const TreeFolder = ({
44
+ export const TreeFolder = ({
45
45
  name,
46
46
  defaultOpen = false,
47
47
  openable = true,
@@ -108,13 +108,13 @@ const TreeFolder = ({
108
108
  );
109
109
  };
110
110
 
111
- const Tree = ({ children }: { children: ReactNode }) => (
111
+ const TreeRoot = ({ children }: { children: ReactNode }) => (
112
112
  <div className="my-4 rounded-xl border border-border bg-card p-4 font-mono text-sm">
113
113
  {children}
114
114
  </div>
115
115
  );
116
116
 
117
- Tree.Folder = TreeFolder;
118
- Tree.File = TreeFile;
119
-
120
- export { Tree };
117
+ export const Tree = Object.assign(TreeRoot, {
118
+ File: TreeFile,
119
+ Folder: TreeFolder,
120
+ });
@@ -17,7 +17,7 @@ import type {
17
17
  MouseEvent as ReactMouseEvent,
18
18
  } from "react";
19
19
 
20
- import { toDocHref } from "@/lib/routes";
20
+ import { isExternalHref, resolveHref, toDocHref } from "@/lib/routes";
21
21
 
22
22
  export interface SearchItem {
23
23
  href?: string;
@@ -134,11 +134,14 @@ export const Search = ({ basePath }: { basePath: string }) => {
134
134
  const runSelection = useCallback(
135
135
  (item: SearchItem) => {
136
136
  closeSearch();
137
- if (item.href) {
138
- window.open(item.href, "_blank", "noopener,noreferrer");
137
+ const href = item.href
138
+ ? resolveHref(item.href, basePath)
139
+ : toDocHref(item.path, basePath);
140
+ if (item.href && isExternalHref(item.href)) {
141
+ window.open(href, "_blank", "noopener,noreferrer");
139
142
  return;
140
143
  }
141
- router.push(toDocHref(item.path, basePath));
144
+ router.push(href);
142
145
  },
143
146
  [basePath, closeSearch, router]
144
147
  );
@@ -346,6 +349,9 @@ export const Search = ({ basePath }: { basePath: string }) => {
346
349
  <div className="grid gap-1">
347
350
  {filteredItems.map((item, index) => {
348
351
  const isActive = index === activeIndex;
352
+ const href = item.href
353
+ ? resolveHref(item.href, basePath)
354
+ : toDocHref(item.path, basePath);
349
355
 
350
356
  return (
351
357
  <button
@@ -363,9 +369,7 @@ export const Search = ({ basePath }: { basePath: string }) => {
363
369
  <span className="text-sm font-medium text-foreground">
364
370
  {item.title}
365
371
  </span>
366
- <span className="text-xs">
367
- {item.href ?? toDocHref(item.path, basePath)}
368
- </span>
372
+ <span className="text-xs">{href}</span>
369
373
  </button>
370
374
  );
371
375
  })}
package/docs/lib/mdx.ts CHANGED
@@ -10,7 +10,7 @@ import remarkGfm from "remark-gfm";
10
10
 
11
11
  import { mdxComponents } from "@/components/mdx";
12
12
 
13
- import { getHighlighter } from "./shiki";
13
+ import { getHighlighter, SHIKI_THEME_PAIR } from "./shiki";
14
14
 
15
15
  const FRONTMATTER_REGEX = /^---\s*\n[\s\S]*?\n---\s*\n?/;
16
16
 
@@ -49,10 +49,7 @@ export const renderMdx = async (source: string) => {
49
49
  const highlighter = await getHighlighter();
50
50
  const shikiTransformer = rehypeShikiFromHighlighter(highlighter, {
51
51
  defaultColor: false,
52
- themes: {
53
- dark: "github-dark",
54
- light: "github-light",
55
- },
52
+ themes: SHIKI_THEME_PAIR,
56
53
  });
57
54
  const shikiPlugin = () => shikiTransformer;
58
55
 
@@ -3,7 +3,7 @@ import type { DocsNavigation } from "@repo/models";
3
3
  import type { PageMetadata } from "@repo/previewing";
4
4
 
5
5
  import type { OpenApiRegistry } from "./openapi";
6
- import { toDocHref } from "./routes";
6
+ import { resolveHref, toDocHref } from "./routes";
7
7
 
8
8
  export interface NavPage {
9
9
  type: "page";
@@ -35,7 +35,7 @@ export const getNavPageTitle = (page: NavPage): string =>
35
35
  page.sidebarTitle ?? page.title;
36
36
 
37
37
  export const getNavPageHref = (page: NavPage, basePath: string): string =>
38
- page.url ?? toDocHref(page.path, basePath);
38
+ page.url ? resolveHref(page.url, basePath) : toDocHref(page.path, basePath);
39
39
 
40
40
  const titleFromSlug = (slug: string) => {
41
41
  const clean = slug.replaceAll("-", " ").split("/").pop() ?? slug;
@@ -1,5 +1,7 @@
1
1
  import { normalizePath, withLeadingSlash } from "@repo/common";
2
2
 
3
+ const ABSOLUTE_URL_REGEX = /^[a-z][a-z\d+.-]*:/i;
4
+
3
5
  export const toDocHref = (path: string, basePath = "") => {
4
6
  const clean = normalizePath(path);
5
7
  const base = basePath ? withLeadingSlash(basePath) : "";
@@ -8,3 +10,35 @@ export const toDocHref = (path: string, basePath = "") => {
8
10
  }
9
11
  return `${base}/${clean}`.replaceAll(/\/+/g, "/");
10
12
  };
13
+
14
+ export const isExternalHref = (href: string) =>
15
+ ABSOLUTE_URL_REGEX.test(href) || href.startsWith("//");
16
+
17
+ export const resolveHref = (href: string, basePath = "") => {
18
+ if (
19
+ !href ||
20
+ href.startsWith("#") ||
21
+ href.startsWith("?") ||
22
+ isExternalHref(href)
23
+ ) {
24
+ return href;
25
+ }
26
+
27
+ const suffixIndex = href.search(/[?#]/);
28
+ const pathPart = suffixIndex === -1 ? href : href.slice(0, suffixIndex);
29
+ const suffix = suffixIndex === -1 ? "" : href.slice(suffixIndex);
30
+ const normalizedBase = basePath
31
+ ? withLeadingSlash(basePath).replaceAll(/\/+$/g, "")
32
+ : "";
33
+ const normalizedPath = withLeadingSlash(pathPart || "/");
34
+
35
+ if (
36
+ normalizedBase &&
37
+ (normalizedPath === normalizedBase ||
38
+ normalizedPath.startsWith(`${normalizedBase}/`))
39
+ ) {
40
+ return `${normalizedPath}${suffix}`;
41
+ }
42
+
43
+ return `${toDocHref(pathPart || "index", basePath)}${suffix}`;
44
+ };
package/docs/lib/shiki.ts CHANGED
@@ -20,7 +20,12 @@ const COMMON_LANGS = [
20
20
  "yaml",
21
21
  ] as const;
22
22
 
23
- const THEMES = ["github-dark", "github-light"] as const;
23
+ export const SHIKI_THEME_PAIR = {
24
+ dark: "github-dark",
25
+ light: "github-light",
26
+ } as const;
27
+
28
+ const THEMES = [SHIKI_THEME_PAIR.dark, SHIKI_THEME_PAIR.light] as const;
24
29
 
25
30
  let highlighterPromise: ReturnType<typeof createHighlighter> | null = null;
26
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blodemd",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Blode.md CLI",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,7 +13,8 @@
13
13
  "dist",
14
14
  "dev-server",
15
15
  "docs",
16
- "packages"
16
+ "packages",
17
+ "scripts/prepare-package.mjs"
17
18
  ],
18
19
  "type": "module",
19
20
  "main": "./dist/index.mjs",
@@ -27,12 +28,13 @@
27
28
  },
28
29
  "scripts": {
29
30
  "build": "tsdown",
30
- "prepublishOnly": "node scripts/prepare-dist.mjs",
31
+ "prepare": "node scripts/prepare-package.mjs",
31
32
  "check-types": "tsc --noEmit -p tsconfig.json",
32
33
  "lint": "oxlint .",
33
34
  "lint:fix": "oxlint --fix .",
34
35
  "format": "oxfmt --write .",
35
- "format:check": "oxfmt ."
36
+ "format:check": "oxfmt .",
37
+ "test:unit": "vitest run --root ../.. --config vitest.unit.config.ts apps/cli/src"
36
38
  },
37
39
  "dependencies": {
38
40
  "@base-ui/react": "^1.3.0",
@@ -40,6 +42,9 @@
40
42
  "@mdx-js/mdx": "^3.1.1",
41
43
  "@shikijs/rehype": "^4.0.2",
42
44
  "@tailwindcss/postcss": "^4.2.2",
45
+ "@types/node": "^22.19.15",
46
+ "@types/react": "19.2.14",
47
+ "@types/react-dom": "19.2.3",
43
48
  "blode-icons-react": "^0.3.10",
44
49
  "chalk": "^5.6.2",
45
50
  "chokidar": "^4.0.3",
@@ -63,16 +68,19 @@
63
68
  "tailwind-merge": "^3.5.0",
64
69
  "tailwindcss": "^4.2.2",
65
70
  "tw-animate-css": "^1.4.0",
71
+ "typescript": "6.0.2",
66
72
  "yaml": "^2.8.3",
67
73
  "zod": "^4.3.6"
68
74
  },
69
75
  "devDependencies": {
70
76
  "@repo/previewing": "*",
71
77
  "@repo/typescript-config": "*",
72
- "@types/node": "^22.15.3",
73
78
  "oxfmt": "^0.42.0",
74
79
  "oxlint": "^1.57.0",
75
80
  "tsdown": "^0.21.5",
76
81
  "ultracite": "^7.3.2"
82
+ },
83
+ "engines": {
84
+ "node": ">=20.17.0 <25"
77
85
  }
78
86
  }
@@ -96,4 +96,16 @@ export declare const TenantEdgeSlugRecordSchema: z.ZodObject<{
96
96
  version: z.ZodLiteral<1>;
97
97
  }, z.core.$strip>;
98
98
  export type TenantEdgeSlugRecord = z.infer<typeof TenantEdgeSlugRecordSchema>;
99
+ export declare const TENANT_EDGE_HOST_KEY_PREFIX = "th_";
100
+ export declare const TENANT_EDGE_SLUG_KEY_PREFIX = "ts_";
101
+ export declare const LEGACY_TENANT_EDGE_HOST_KEY_PREFIX = "tenant:host:";
102
+ export declare const LEGACY_TENANT_EDGE_SLUG_KEY_PREFIX = "tenant:slug:";
103
+ export declare const normalizeTenantEdgeHost: (host: string) => string;
104
+ export declare const normalizeTenantEdgeSlug: (slug: string) => string;
105
+ export declare const getTenantEdgeHostKey: (host: string) => string;
106
+ export declare const getTenantEdgeSlugKey: (slug: string) => string;
107
+ export declare const getLegacyTenantEdgeHostKey: (host: string) => string;
108
+ export declare const getLegacyTenantEdgeSlugKey: (slug: string) => string;
109
+ export declare const getTenantEdgeHostKeys: (host: string) => string[];
110
+ export declare const getTenantEdgeSlugKeys: (slug: string) => string[];
99
111
  //# sourceMappingURL=tenant.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../src/tenant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,eAAO,MAAM,kBAAkB;;;EAAiC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;iBAYvB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;iBAMrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;iBAIrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
1
+ {"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../src/tenant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,eAAO,MAAM,kBAAkB;;;EAAiC,CAAC;AACjE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;iBAYvB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAItE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;iBAMrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;iBAIrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AACjD,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AACjD,eAAO,MAAM,kCAAkC,iBAAiB,CAAC;AACjE,eAAO,MAAM,kCAAkC,iBAAiB,CAAC;AAEjE,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,WACJ,CAAC;AAEjD,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,WACzB,CAAC;AAO5B,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,WACc,CAAC;AAEhE,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,WACc,CAAC;AAEhE,eAAO,MAAM,0BAA0B,GAAI,MAAM,MAAM,WACkB,CAAC;AAE1E,eAAO,MAAM,0BAA0B,GAAI,MAAM,MAAM,WACkB,CAAC;AAE1E,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,aAGjD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,aAGjD,CAAC"}
@@ -34,3 +34,23 @@ export const TenantEdgeSlugRecordSchema = z.object({
34
34
  tenant: TenantSchema,
35
35
  version: TenantEdgeRecordVersionSchema,
36
36
  });
37
+ export const TENANT_EDGE_HOST_KEY_PREFIX = "th_";
38
+ export const TENANT_EDGE_SLUG_KEY_PREFIX = "ts_";
39
+ export const LEGACY_TENANT_EDGE_HOST_KEY_PREFIX = "tenant:host:";
40
+ export const LEGACY_TENANT_EDGE_SLUG_KEY_PREFIX = "tenant:slug:";
41
+ export const normalizeTenantEdgeHost = (host) => host.trim().toLowerCase().replace(/:\d+$/, "");
42
+ export const normalizeTenantEdgeSlug = (slug) => slug.trim().toLowerCase();
43
+ const encodeTenantEdgeHost = (host) => normalizeTenantEdgeHost(host).replaceAll(".", "_");
44
+ const encodeTenantEdgeSlug = (slug) => normalizeTenantEdgeSlug(slug);
45
+ export const getTenantEdgeHostKey = (host) => `${TENANT_EDGE_HOST_KEY_PREFIX}${encodeTenantEdgeHost(host)}`;
46
+ export const getTenantEdgeSlugKey = (slug) => `${TENANT_EDGE_SLUG_KEY_PREFIX}${encodeTenantEdgeSlug(slug)}`;
47
+ export const getLegacyTenantEdgeHostKey = (host) => `${LEGACY_TENANT_EDGE_HOST_KEY_PREFIX}${normalizeTenantEdgeHost(host)}`;
48
+ export const getLegacyTenantEdgeSlugKey = (slug) => `${LEGACY_TENANT_EDGE_SLUG_KEY_PREFIX}${normalizeTenantEdgeSlug(slug)}`;
49
+ export const getTenantEdgeHostKeys = (host) => [
50
+ getTenantEdgeHostKey(host),
51
+ getLegacyTenantEdgeHostKey(host),
52
+ ];
53
+ export const getTenantEdgeSlugKeys = (slug) => [
54
+ getTenantEdgeSlugKey(slug),
55
+ getLegacyTenantEdgeSlugKey(slug),
56
+ ];
@@ -52,3 +52,41 @@ export const TenantEdgeSlugRecordSchema = z.object({
52
52
  version: TenantEdgeRecordVersionSchema,
53
53
  });
54
54
  export type TenantEdgeSlugRecord = z.infer<typeof TenantEdgeSlugRecordSchema>;
55
+
56
+ export const TENANT_EDGE_HOST_KEY_PREFIX = "th_";
57
+ export const TENANT_EDGE_SLUG_KEY_PREFIX = "ts_";
58
+ export const LEGACY_TENANT_EDGE_HOST_KEY_PREFIX = "tenant:host:";
59
+ export const LEGACY_TENANT_EDGE_SLUG_KEY_PREFIX = "tenant:slug:";
60
+
61
+ export const normalizeTenantEdgeHost = (host: string) =>
62
+ host.trim().toLowerCase().replace(/:\d+$/, "");
63
+
64
+ export const normalizeTenantEdgeSlug = (slug: string) =>
65
+ slug.trim().toLowerCase();
66
+
67
+ const encodeTenantEdgeHost = (host: string) =>
68
+ normalizeTenantEdgeHost(host).replaceAll(".", "_");
69
+
70
+ const encodeTenantEdgeSlug = (slug: string) => normalizeTenantEdgeSlug(slug);
71
+
72
+ export const getTenantEdgeHostKey = (host: string) =>
73
+ `${TENANT_EDGE_HOST_KEY_PREFIX}${encodeTenantEdgeHost(host)}`;
74
+
75
+ export const getTenantEdgeSlugKey = (slug: string) =>
76
+ `${TENANT_EDGE_SLUG_KEY_PREFIX}${encodeTenantEdgeSlug(slug)}`;
77
+
78
+ export const getLegacyTenantEdgeHostKey = (host: string) =>
79
+ `${LEGACY_TENANT_EDGE_HOST_KEY_PREFIX}${normalizeTenantEdgeHost(host)}`;
80
+
81
+ export const getLegacyTenantEdgeSlugKey = (slug: string) =>
82
+ `${LEGACY_TENANT_EDGE_SLUG_KEY_PREFIX}${normalizeTenantEdgeSlug(slug)}`;
83
+
84
+ export const getTenantEdgeHostKeys = (host: string) => [
85
+ getTenantEdgeHostKey(host),
86
+ getLegacyTenantEdgeHostKey(host),
87
+ ];
88
+
89
+ export const getTenantEdgeSlugKeys = (slug: string) => [
90
+ getTenantEdgeSlugKey(slug),
91
+ getLegacyTenantEdgeSlugKey(slug),
92
+ ];
@@ -1 +1 @@
1
- {"version":3,"file":"fs-source.d.ts","sourceRoot":"","sources":["../src/fs-source.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAoEzD,qBAAa,eAAgB,YAAW,aAAa;IACnD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,IAAI,EAAE,MAAM;IAIlB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO/C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAI/C,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAapD,UAAU,IAAI,MAAM,GAAG,IAAI;CAG5B;AAED,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,aACnB,CAAC"}
1
+ {"version":3,"file":"fs-source.d.ts","sourceRoot":"","sources":["../src/fs-source.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA6DzD,qBAAa,eAAgB,YAAW,aAAa;IACnD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,IAAI,EAAE,MAAM;IAIlB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO/C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAI/C,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAapD,UAAU,IAAI,MAAM,GAAG,IAAI;CAG5B;AAED,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,aACnB,CAAC"}
@@ -1,14 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { normalizePath } from "@repo/common";
4
- const IGNORED_DIRECTORIES = new Set([
5
- "app",
6
- "components",
7
- "content",
8
- "lib",
9
- "node_modules",
10
- "public",
11
- ]);
4
+ const IGNORED_DIRECTORIES = new Set(["app", "lib", "node_modules", "public"]);
12
5
  const IGNORED_ROOT_FILES = new Set(["AGENTS.md", "README.md"]);
13
6
  const isNotFoundError = (error) => Boolean(error &&
14
7
  typeof error === "object" &&
@@ -5,14 +5,7 @@ import { normalizePath } from "@repo/common";
5
5
 
6
6
  import type { ContentSource } from "./content-source.js";
7
7
 
8
- const IGNORED_DIRECTORIES = new Set([
9
- "app",
10
- "components",
11
- "content",
12
- "lib",
13
- "node_modules",
14
- "public",
15
- ]);
8
+ const IGNORED_DIRECTORIES = new Set(["app", "lib", "node_modules", "public"]);
16
9
  const IGNORED_ROOT_FILES = new Set(["AGENTS.md", "README.md"]);
17
10
 
18
11
  const isNotFoundError = (error: unknown) =>
@@ -10,7 +10,7 @@
10
10
  "$schema": {
11
11
  "type": "string",
12
12
  "format": "uri",
13
- "default": "https://mintlify.com/docs.json",
13
+ "default": "https://docs.blode.md/docs.json",
14
14
  "description": "The URL of the schema file"
15
15
  },
16
16
  "name": {
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execSync } from "node:child_process";
4
+ import { existsSync } from "node:fs";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const cliRoot = path.resolve(__dirname, "..");
10
+ const repoRoot = path.resolve(cliRoot, "../..");
11
+
12
+ const command = process.env.npm_command;
13
+ const isGlobalInstall = process.env.npm_config_global === "true";
14
+ const shouldPackage = command === "pack" || command === "publish";
15
+
16
+ const hasRepoSources =
17
+ existsSync(path.join(repoRoot, "apps", "dev-server")) &&
18
+ existsSync(path.join(repoRoot, "packages", "previewing"));
19
+
20
+ if (!hasRepoSources) {
21
+ console.log("Skipping standalone package preparation outside the monorepo.");
22
+ process.exit(0);
23
+ }
24
+
25
+ if (!shouldPackage && !isGlobalInstall) {
26
+ process.exit(0);
27
+ }
28
+
29
+ console.log("Preparing blodemd standalone package...");
30
+
31
+ execSync("npm run build", {
32
+ cwd: cliRoot,
33
+ stdio: "inherit",
34
+ });
35
+
36
+ execSync("node scripts/prepare-dist.mjs", {
37
+ cwd: cliRoot,
38
+ stdio: "inherit",
39
+ });