blodemd 0.1.0 → 0.2.0
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/dist/cli.mjs +50 -174
- package/dist/cli.mjs.map +1 -1
- package/package.json +3 -36
- package/dev-server/app/[[...slug]]/page.tsx +0 -140
- package/dev-server/app/blodemd-dev/invalidate/route.ts +0 -12
- package/dev-server/app/blodemd-dev/static/[...path]/route.ts +0 -32
- package/dev-server/app/blodemd-dev/version/route.ts +0 -14
- package/dev-server/app/blodemd-internal/proxy/route.ts +0 -86
- package/dev-server/app/error.tsx +0 -24
- package/dev-server/app/favicon.ico +0 -0
- package/dev-server/app/globals.css +0 -4
- package/dev-server/app/layout.tsx +0 -38
- package/dev-server/app/not-found.tsx +0 -18
- package/dev-server/app/search/route.ts +0 -17
- package/dev-server/components/dev-reload-script.tsx +0 -86
- package/dev-server/components/providers.tsx +0 -15
- package/dev-server/lib/dev-state.ts +0 -8
- package/dev-server/lib/local-content-source.ts +0 -103
- package/dev-server/lib/local-runtime.tsx +0 -555
- package/dev-server/next-env.d.ts +0 -5
- package/dev-server/next.config.js +0 -54
- package/dev-server/package.json +0 -61
- package/dev-server/postcss.config.mjs +0 -7
- package/dev-server/public/glide-variable.woff2 +0 -0
- package/dev-server/tsconfig.json +0 -50
- package/docs/app/globals.css +0 -471
- package/docs/components/animate-ui/primitives/buttons/button.tsx +0 -14
- package/docs/components/api/api-playground.tsx +0 -467
- package/docs/components/api/api-reference.tsx +0 -157
- package/docs/components/content/collection-index.tsx +0 -114
- package/docs/components/docs/contextual-menu.tsx +0 -495
- package/docs/components/docs/copy-page-menu.tsx +0 -364
- package/docs/components/docs/doc-header.tsx +0 -223
- package/docs/components/docs/doc-shell.tsx +0 -355
- package/docs/components/docs/doc-sidebar.tsx +0 -256
- package/docs/components/docs/doc-toc.tsx +0 -46
- package/docs/components/docs/mobile-nav.tsx +0 -195
- package/docs/components/docs/sidebar-active-highlight.tsx +0 -34
- package/docs/components/docs/sidebar-scroll-area.tsx +0 -63
- package/docs/components/git/repo-picker.tsx +0 -529
- package/docs/components/icons/doc-icon.tsx +0 -96
- package/docs/components/mdx/accordion.tsx +0 -83
- package/docs/components/mdx/agent-instructions.tsx +0 -17
- package/docs/components/mdx/badge.tsx +0 -79
- package/docs/components/mdx/callout.tsx +0 -88
- package/docs/components/mdx/card.tsx +0 -110
- package/docs/components/mdx/code-block.tsx +0 -80
- package/docs/components/mdx/code-group.tsx +0 -203
- package/docs/components/mdx/color.tsx +0 -87
- package/docs/components/mdx/columns.tsx +0 -25
- package/docs/components/mdx/expandable.tsx +0 -45
- package/docs/components/mdx/field-layout.tsx +0 -77
- package/docs/components/mdx/frame.tsx +0 -23
- package/docs/components/mdx/get-text-content.ts +0 -18
- package/docs/components/mdx/icon.tsx +0 -12
- package/docs/components/mdx/iframe.tsx +0 -62
- package/docs/components/mdx/index.tsx +0 -121
- package/docs/components/mdx/installer.tsx +0 -20
- package/docs/components/mdx/panel.tsx +0 -11
- package/docs/components/mdx/param-field.tsx +0 -56
- package/docs/components/mdx/preview.tsx +0 -36
- package/docs/components/mdx/prompt.tsx +0 -63
- package/docs/components/mdx/request-example.tsx +0 -27
- package/docs/components/mdx/response-field.tsx +0 -42
- package/docs/components/mdx/steps.tsx +0 -92
- package/docs/components/mdx/tabs.tsx +0 -193
- package/docs/components/mdx/tile.tsx +0 -43
- package/docs/components/mdx/tooltip.tsx +0 -71
- package/docs/components/mdx/tree.tsx +0 -120
- package/docs/components/mdx/type-table.tsx +0 -71
- package/docs/components/mdx/update.tsx +0 -44
- package/docs/components/mdx/video.tsx +0 -45
- package/docs/components/mdx/view.tsx +0 -66
- package/docs/components/posthog-provider.tsx +0 -42
- package/docs/components/providers.tsx +0 -15
- package/docs/components/tenant-analytics.tsx +0 -49
- package/docs/components/third-parties.tsx +0 -32
- package/docs/components/ui/badge.tsx +0 -61
- package/docs/components/ui/breadcrumb.tsx +0 -112
- package/docs/components/ui/button-group.tsx +0 -83
- package/docs/components/ui/button.tsx +0 -65
- package/docs/components/ui/card.tsx +0 -92
- package/docs/components/ui/command.tsx +0 -167
- package/docs/components/ui/copy-button.tsx +0 -129
- package/docs/components/ui/dialog.tsx +0 -146
- package/docs/components/ui/field.tsx +0 -237
- package/docs/components/ui/input.tsx +0 -23
- package/docs/components/ui/kbd.tsx +0 -98
- package/docs/components/ui/label.tsx +0 -22
- package/docs/components/ui/morph-icon.tsx +0 -79
- package/docs/components/ui/popover.tsx +0 -267
- package/docs/components/ui/search-dialog.tsx +0 -431
- package/docs/components/ui/search.tsx +0 -101
- package/docs/components/ui/separator.tsx +0 -26
- package/docs/components/ui/sheet.tsx +0 -133
- package/docs/components/ui/sidebar.tsx +0 -758
- package/docs/components/ui/skeleton.tsx +0 -11
- package/docs/components/ui/switch.tsx +0 -32
- package/docs/components/ui/tabs.tsx +0 -138
- package/docs/components/ui/theme-toggle.tsx +0 -62
- package/docs/components/ui/tooltip.tsx +0 -53
- package/docs/components/web-mcp.tsx +0 -115
- package/docs/lib/agent-skills.ts +0 -48
- package/docs/lib/api-client.ts +0 -72
- package/docs/lib/config.ts +0 -6
- package/docs/lib/content-root.ts +0 -33
- package/docs/lib/content-source.ts +0 -70
- package/docs/lib/contextual-options.ts +0 -222
- package/docs/lib/dashboard-session.ts +0 -167
- package/docs/lib/db.ts +0 -13
- package/docs/lib/docs-collection.ts +0 -7
- package/docs/lib/docs-runtime.tsx +0 -745
- package/docs/lib/edge-config.ts +0 -95
- package/docs/lib/env.ts +0 -23
- package/docs/lib/etag.ts +0 -22
- package/docs/lib/github-install.ts +0 -33
- package/docs/lib/llms-full.ts +0 -82
- package/docs/lib/marketing-markdown.ts +0 -79
- package/docs/lib/marketing-site.ts +0 -31
- package/docs/lib/mdx.ts +0 -98
- package/docs/lib/navigation.ts +0 -288
- package/docs/lib/openapi-proxy.ts +0 -88
- package/docs/lib/openapi.ts +0 -158
- package/docs/lib/platform-config.ts +0 -6
- package/docs/lib/project-authz.ts +0 -46
- package/docs/lib/routes.ts +0 -103
- package/docs/lib/server-cache.ts +0 -83
- package/docs/lib/shiki.ts +0 -44
- package/docs/lib/supabase.ts +0 -37
- package/docs/lib/tenancy.ts +0 -364
- package/docs/lib/tenant-headers.ts +0 -43
- package/docs/lib/tenant-static.ts +0 -705
- package/docs/lib/tenant-utility-context.ts +0 -62
- package/docs/lib/tenants.ts +0 -72
- package/docs/lib/theme.ts +0 -29
- package/docs/lib/time-ago.ts +0 -24
- package/docs/lib/toc.ts +0 -2
- package/docs/lib/use-mobile.ts +0 -19
- package/docs/lib/use-tab-observer.ts +0 -71
- package/docs/lib/utils.ts +0 -5
- package/packages/@repo/common/dist/index.d.ts +0 -16
- package/packages/@repo/common/dist/index.d.ts.map +0 -1
- package/packages/@repo/common/dist/index.js +0 -84
- package/packages/@repo/common/package.json +0 -34
- package/packages/@repo/common/src/index.ts +0 -101
- package/packages/@repo/contracts/dist/analytics.d.ts +0 -21
- package/packages/@repo/contracts/dist/analytics.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/analytics.js +0 -18
- package/packages/@repo/contracts/dist/api-key.d.ts +0 -27
- package/packages/@repo/contracts/dist/api-key.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/api-key.js +0 -20
- package/packages/@repo/contracts/dist/dates.d.ts +0 -4
- package/packages/@repo/contracts/dist/dates.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/dates.js +0 -2
- package/packages/@repo/contracts/dist/deployment.d.ts +0 -71
- package/packages/@repo/contracts/dist/deployment.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/deployment.js +0 -46
- package/packages/@repo/contracts/dist/domain.d.ts +0 -94
- package/packages/@repo/contracts/dist/domain.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/domain.js +0 -36
- package/packages/@repo/contracts/dist/git.d.ts +0 -28
- package/packages/@repo/contracts/dist/git.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/git.js +0 -24
- package/packages/@repo/contracts/dist/ids.d.ts +0 -14
- package/packages/@repo/contracts/dist/ids.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/ids.js +0 -11
- package/packages/@repo/contracts/dist/index.d.ts +0 -12
- package/packages/@repo/contracts/dist/index.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/index.js +0 -13
- package/packages/@repo/contracts/dist/pagination.d.ts +0 -23
- package/packages/@repo/contracts/dist/pagination.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/pagination.js +0 -15
- package/packages/@repo/contracts/dist/project.d.ts +0 -42
- package/packages/@repo/contracts/dist/project.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/project.js +0 -25
- package/packages/@repo/contracts/dist/tenant.d.ts +0 -147
- package/packages/@repo/contracts/dist/tenant.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/tenant.js +0 -58
- package/packages/@repo/contracts/dist/user.d.ts +0 -9
- package/packages/@repo/contracts/dist/user.d.ts.map +0 -1
- package/packages/@repo/contracts/dist/user.js +0 -9
- package/packages/@repo/contracts/package.json +0 -37
- package/packages/@repo/contracts/src/analytics.ts +0 -33
- package/packages/@repo/contracts/src/api-key.ts +0 -27
- package/packages/@repo/contracts/src/dates.ts +0 -4
- package/packages/@repo/contracts/src/deployment.ts +0 -73
- package/packages/@repo/contracts/src/domain.ts +0 -51
- package/packages/@repo/contracts/src/git.ts +0 -31
- package/packages/@repo/contracts/src/ids.ts +0 -23
- package/packages/@repo/contracts/src/index.ts +0 -13
- package/packages/@repo/contracts/src/pagination.ts +0 -21
- package/packages/@repo/contracts/src/project.ts +0 -32
- package/packages/@repo/contracts/src/tenant.ts +0 -94
- package/packages/@repo/contracts/src/user.ts +0 -12
- package/packages/@repo/models/dist/docs-config.d.ts +0 -961
- package/packages/@repo/models/dist/docs-config.d.ts.map +0 -1
- package/packages/@repo/models/dist/docs-config.js +0 -531
- package/packages/@repo/models/dist/index.d.ts +0 -3
- package/packages/@repo/models/dist/index.d.ts.map +0 -1
- package/packages/@repo/models/dist/index.js +0 -3
- package/packages/@repo/models/dist/tenant.d.ts +0 -37
- package/packages/@repo/models/dist/tenant.d.ts.map +0 -1
- package/packages/@repo/models/dist/tenant.js +0 -1
- package/packages/@repo/models/package.json +0 -37
- package/packages/@repo/models/src/docs-config.ts +0 -629
- package/packages/@repo/models/src/index.ts +0 -3
- package/packages/@repo/models/src/tenant.ts +0 -44
- package/packages/@repo/prebuild/dist/index.d.ts +0 -2
- package/packages/@repo/prebuild/dist/index.d.ts.map +0 -1
- package/packages/@repo/prebuild/dist/index.js +0 -2
- package/packages/@repo/prebuild/dist/openapi.d.ts +0 -43
- package/packages/@repo/prebuild/dist/openapi.d.ts.map +0 -1
- package/packages/@repo/prebuild/dist/openapi.js +0 -86
- package/packages/@repo/prebuild/package.json +0 -39
- package/packages/@repo/prebuild/src/index.ts +0 -2
- package/packages/@repo/prebuild/src/openapi.ts +0 -154
- package/packages/@repo/previewing/dist/blob-source.d.ts +0 -16
- package/packages/@repo/previewing/dist/blob-source.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/blob-source.js +0 -128
- package/packages/@repo/previewing/dist/config-loader.d.ts +0 -134
- package/packages/@repo/previewing/dist/config-loader.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/config-loader.js +0 -231
- package/packages/@repo/previewing/dist/constants.d.ts +0 -15
- package/packages/@repo/previewing/dist/constants.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/constants.js +0 -14
- package/packages/@repo/previewing/dist/content-index.d.ts +0 -7
- package/packages/@repo/previewing/dist/content-index.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/content-index.js +0 -291
- package/packages/@repo/previewing/dist/content-source.d.ts +0 -12
- package/packages/@repo/previewing/dist/content-source.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/content-source.js +0 -1
- package/packages/@repo/previewing/dist/fs-source.d.ts +0 -11
- package/packages/@repo/previewing/dist/fs-source.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/fs-source.js +0 -71
- package/packages/@repo/previewing/dist/index.d.ts +0 -16
- package/packages/@repo/previewing/dist/index.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/index.js +0 -13
- package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts +0 -3
- package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/markdown/agent-markdown.js +0 -176
- package/packages/@repo/previewing/dist/markdown/format.d.ts +0 -8
- package/packages/@repo/previewing/dist/markdown/format.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/markdown/format.js +0 -43
- package/packages/@repo/previewing/dist/markdown/links.d.ts +0 -3
- package/packages/@repo/previewing/dist/markdown/links.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/markdown/links.js +0 -31
- package/packages/@repo/previewing/dist/openapi-pages.d.ts +0 -7
- package/packages/@repo/previewing/dist/openapi-pages.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/openapi-pages.js +0 -200
- package/packages/@repo/previewing/dist/search-index.d.ts +0 -4
- package/packages/@repo/previewing/dist/search-index.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/search-index.js +0 -23
- package/packages/@repo/previewing/dist/serialization.d.ts +0 -13
- package/packages/@repo/previewing/dist/serialization.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/serialization.js +0 -108
- package/packages/@repo/previewing/dist/toc-index.d.ts +0 -5
- package/packages/@repo/previewing/dist/toc-index.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/toc-index.js +0 -53
- package/packages/@repo/previewing/dist/types.d.ts +0 -92
- package/packages/@repo/previewing/dist/types.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/types.js +0 -1
- package/packages/@repo/previewing/dist/utility-index.d.ts +0 -7
- package/packages/@repo/previewing/dist/utility-index.d.ts.map +0 -1
- package/packages/@repo/previewing/dist/utility-index.js +0 -201
- package/packages/@repo/previewing/package.json +0 -41
- package/packages/@repo/previewing/src/blob-source.ts +0 -185
- package/packages/@repo/previewing/src/config-loader.ts +0 -316
- package/packages/@repo/previewing/src/constants.ts +0 -16
- package/packages/@repo/previewing/src/content-index.ts +0 -384
- package/packages/@repo/previewing/src/content-source.ts +0 -12
- package/packages/@repo/previewing/src/fs-source.ts +0 -103
- package/packages/@repo/previewing/src/index.ts +0 -71
- package/packages/@repo/previewing/src/markdown/agent-markdown.ts +0 -254
- package/packages/@repo/previewing/src/markdown/format.ts +0 -63
- package/packages/@repo/previewing/src/markdown/links.ts +0 -46
- package/packages/@repo/previewing/src/openapi-pages.ts +0 -319
- package/packages/@repo/previewing/src/search-index.ts +0 -38
- package/packages/@repo/previewing/src/serialization.ts +0 -191
- package/packages/@repo/previewing/src/toc-index.ts +0 -72
- package/packages/@repo/previewing/src/types.ts +0 -105
- package/packages/@repo/previewing/src/utility-index.ts +0 -304
- package/packages/@repo/validation/dist/index.d.ts +0 -12
- package/packages/@repo/validation/dist/index.d.ts.map +0 -1
- package/packages/@repo/validation/dist/index.js +0 -30
- package/packages/@repo/validation/package.json +0 -38
- package/packages/@repo/validation/src/blodemd-docs-schema.json +0 -3575
- package/packages/@repo/validation/src/index.ts +0 -59
- package/scripts/prepare-package.mjs +0 -53
- package/scripts/repo-packages.mjs +0 -8
package/docs/lib/navigation.ts
DELETED
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import { normalizePath } from "@repo/common";
|
|
2
|
-
import type { DocsNavigation } from "@repo/models";
|
|
3
|
-
import type { PageMetadata } from "@repo/previewing";
|
|
4
|
-
|
|
5
|
-
import type { OpenApiRegistry } from "./openapi";
|
|
6
|
-
import { resolveHref, toDocHref } from "./routes";
|
|
7
|
-
|
|
8
|
-
export interface NavPage {
|
|
9
|
-
type: "page";
|
|
10
|
-
title: string;
|
|
11
|
-
path: string;
|
|
12
|
-
source: "mdx" | "openapi";
|
|
13
|
-
identifier?: string;
|
|
14
|
-
sidebarTitle?: string;
|
|
15
|
-
icon?: string;
|
|
16
|
-
iconType?: string;
|
|
17
|
-
tag?: string;
|
|
18
|
-
hidden?: boolean;
|
|
19
|
-
deprecated?: boolean;
|
|
20
|
-
url?: string;
|
|
21
|
-
hideApiMarker?: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface NavGroup {
|
|
25
|
-
type: "group";
|
|
26
|
-
title: string;
|
|
27
|
-
items: NavPage[];
|
|
28
|
-
expanded?: boolean;
|
|
29
|
-
hidden?: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export type NavEntry = NavGroup | NavPage;
|
|
33
|
-
|
|
34
|
-
export const getNavPageTitle = (page: NavPage): string =>
|
|
35
|
-
page.sidebarTitle ?? page.title;
|
|
36
|
-
|
|
37
|
-
export const getNavPageHref = (page: NavPage, basePath: string): string =>
|
|
38
|
-
page.url ? resolveHref(page.url, basePath) : toDocHref(page.path, basePath);
|
|
39
|
-
|
|
40
|
-
const titleFromSlug = (slug: string) => {
|
|
41
|
-
const clean = slug.replaceAll("-", " ").split("/").pop() ?? slug;
|
|
42
|
-
if (clean === "index") {
|
|
43
|
-
return "Overview";
|
|
44
|
-
}
|
|
45
|
-
return clean.replaceAll(/\b\w/g, (char) => char.toUpperCase());
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const createPageItem = (
|
|
49
|
-
page: string,
|
|
50
|
-
registry: OpenApiRegistry,
|
|
51
|
-
slugPrefix: string
|
|
52
|
-
): NavPage => {
|
|
53
|
-
const entry = registry.byIdentifier.get(page);
|
|
54
|
-
if (entry) {
|
|
55
|
-
return {
|
|
56
|
-
identifier: entry.identifier,
|
|
57
|
-
path: entry.slug,
|
|
58
|
-
source: "openapi",
|
|
59
|
-
title: entry.operation.summary ?? entry.identifier,
|
|
60
|
-
type: "page",
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const normalized = normalizePath(page);
|
|
65
|
-
const path = slugPrefix
|
|
66
|
-
? normalizePath(`${slugPrefix}/${normalized}`)
|
|
67
|
-
: normalized;
|
|
68
|
-
|
|
69
|
-
return {
|
|
70
|
-
path,
|
|
71
|
-
source: "mdx",
|
|
72
|
-
title: titleFromSlug(page),
|
|
73
|
-
type: "page",
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// oxlint-disable-next-line eslint/complexity
|
|
78
|
-
export const buildNavigation = (
|
|
79
|
-
navigation: DocsNavigation | undefined,
|
|
80
|
-
registry: OpenApiRegistry,
|
|
81
|
-
slugPrefix = ""
|
|
82
|
-
) => {
|
|
83
|
-
const entries: NavEntry[] = [];
|
|
84
|
-
const groups = navigation?.groups ?? [];
|
|
85
|
-
const hiddenPages = new Set(navigation?.hidden);
|
|
86
|
-
|
|
87
|
-
for (const group of groups) {
|
|
88
|
-
const title = group.group ?? "Untitled";
|
|
89
|
-
const items: NavPage[] = [];
|
|
90
|
-
const groupHidden = group.hidden === true;
|
|
91
|
-
|
|
92
|
-
if (group.pages?.length) {
|
|
93
|
-
for (const page of group.pages) {
|
|
94
|
-
const item = createPageItem(page, registry, slugPrefix);
|
|
95
|
-
if (groupHidden || hiddenPages.has(page)) {
|
|
96
|
-
item.hidden = true;
|
|
97
|
-
}
|
|
98
|
-
items.push(item);
|
|
99
|
-
}
|
|
100
|
-
} else if (group.openapi) {
|
|
101
|
-
const sourceKey =
|
|
102
|
-
typeof group.openapi === "string"
|
|
103
|
-
? `${group.openapi}::::`
|
|
104
|
-
: `${group.openapi.source}::${group.openapi.directory ?? ""}::${(
|
|
105
|
-
group.openapi.include ?? []
|
|
106
|
-
).join("|")}`;
|
|
107
|
-
const sourceEntries = registry.bySource.get(sourceKey) ?? [];
|
|
108
|
-
for (const entry of sourceEntries) {
|
|
109
|
-
items.push({
|
|
110
|
-
hidden: groupHidden || undefined,
|
|
111
|
-
identifier: entry.identifier,
|
|
112
|
-
path: entry.slug,
|
|
113
|
-
source: "openapi",
|
|
114
|
-
title: entry.operation.summary ?? entry.identifier,
|
|
115
|
-
type: "page",
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (items.length) {
|
|
121
|
-
entries.push({
|
|
122
|
-
expanded: group.expanded,
|
|
123
|
-
hidden: groupHidden || undefined,
|
|
124
|
-
items,
|
|
125
|
-
title,
|
|
126
|
-
type: "group",
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const topPages = navigation?.pages ?? [];
|
|
132
|
-
for (const page of topPages) {
|
|
133
|
-
const item = createPageItem(page, registry, slugPrefix);
|
|
134
|
-
if (hiddenPages.has(page)) {
|
|
135
|
-
item.hidden = true;
|
|
136
|
-
}
|
|
137
|
-
entries.push(item);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return entries;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const enrichPage = (
|
|
144
|
-
page: NavPage,
|
|
145
|
-
metadataMap: Map<string, PageMetadata>
|
|
146
|
-
): NavPage => {
|
|
147
|
-
const meta = metadataMap.get(page.path);
|
|
148
|
-
if (!meta) {
|
|
149
|
-
return page;
|
|
150
|
-
}
|
|
151
|
-
return {
|
|
152
|
-
...page,
|
|
153
|
-
deprecated: meta.deprecated ?? page.deprecated,
|
|
154
|
-
hidden: meta.hidden ?? page.hidden,
|
|
155
|
-
hideApiMarker: meta.hideApiMarker ?? page.hideApiMarker,
|
|
156
|
-
icon: meta.icon ?? page.icon,
|
|
157
|
-
iconType: meta.iconType ?? page.iconType,
|
|
158
|
-
sidebarTitle: meta.sidebarTitle ?? page.sidebarTitle,
|
|
159
|
-
tag: meta.tag ?? page.tag,
|
|
160
|
-
title: meta.title ?? page.title,
|
|
161
|
-
url: meta.url ?? page.url,
|
|
162
|
-
};
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
export const enrichNavWithMetadata = (
|
|
166
|
-
entries: NavEntry[],
|
|
167
|
-
metadataMap: Map<string, PageMetadata>
|
|
168
|
-
): NavEntry[] =>
|
|
169
|
-
entries.map((entry) => {
|
|
170
|
-
if (entry.type === "page") {
|
|
171
|
-
return enrichPage(entry, metadataMap);
|
|
172
|
-
}
|
|
173
|
-
return {
|
|
174
|
-
...entry,
|
|
175
|
-
items: entry.items.map((item) => enrichPage(item, metadataMap)),
|
|
176
|
-
};
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
export const getVisibleNavigation = (entries: NavEntry[]): NavEntry[] => {
|
|
180
|
-
const visible: NavEntry[] = [];
|
|
181
|
-
for (const entry of entries) {
|
|
182
|
-
if (entry.hidden) {
|
|
183
|
-
continue;
|
|
184
|
-
}
|
|
185
|
-
if (entry.type === "group") {
|
|
186
|
-
const visibleItems = entry.items.filter((item) => !item.hidden);
|
|
187
|
-
if (visibleItems.length) {
|
|
188
|
-
visible.push({ ...entry, items: visibleItems });
|
|
189
|
-
}
|
|
190
|
-
} else {
|
|
191
|
-
visible.push(entry);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return visible;
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
export const flattenNav = (entries: NavEntry[]): NavPage[] => {
|
|
198
|
-
const pages: NavPage[] = [];
|
|
199
|
-
for (const entry of entries) {
|
|
200
|
-
if (entry.type === "page") {
|
|
201
|
-
pages.push(entry);
|
|
202
|
-
} else {
|
|
203
|
-
pages.push(...entry.items);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return pages;
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
export interface NavTab {
|
|
210
|
-
label: string;
|
|
211
|
-
icon?: string;
|
|
212
|
-
href?: string;
|
|
213
|
-
entries: NavEntry[];
|
|
214
|
-
slugPrefix?: string;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
export const buildTabbedNavigation = (
|
|
218
|
-
navigation: DocsNavigation | undefined,
|
|
219
|
-
registry: OpenApiRegistry,
|
|
220
|
-
slugPrefix = ""
|
|
221
|
-
): NavTab[] | null => {
|
|
222
|
-
if (!navigation?.tabs?.length) {
|
|
223
|
-
return null;
|
|
224
|
-
}
|
|
225
|
-
const { tabs } = navigation;
|
|
226
|
-
|
|
227
|
-
return tabs.map((tab) => {
|
|
228
|
-
if (tab.href) {
|
|
229
|
-
return {
|
|
230
|
-
entries: [],
|
|
231
|
-
href: tab.href,
|
|
232
|
-
icon: tab.icon,
|
|
233
|
-
label: tab.label,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const tabNav: DocsNavigation = {
|
|
238
|
-
groups: tab.groups,
|
|
239
|
-
hidden: navigation.hidden,
|
|
240
|
-
pages: tab.pages,
|
|
241
|
-
};
|
|
242
|
-
const entries = buildNavigation(tabNav, registry, slugPrefix);
|
|
243
|
-
const [firstPage] = flattenNav(entries);
|
|
244
|
-
|
|
245
|
-
return {
|
|
246
|
-
entries,
|
|
247
|
-
icon: tab.icon,
|
|
248
|
-
label: tab.label,
|
|
249
|
-
slugPrefix: firstPage?.path,
|
|
250
|
-
};
|
|
251
|
-
});
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
export const findActiveTabIndex = (
|
|
255
|
-
tabs: NavTab[],
|
|
256
|
-
currentPath: string
|
|
257
|
-
): number => {
|
|
258
|
-
const normalized = normalizePath(currentPath);
|
|
259
|
-
for (const [index, tab] of tabs.entries()) {
|
|
260
|
-
if (tab.href) {
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
const pages = flattenNav(tab.entries);
|
|
264
|
-
if (pages.some((page) => page.path === normalized)) {
|
|
265
|
-
return index;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
return 0;
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
export const findBreadcrumbs = (entries: NavEntry[], path: string) => {
|
|
272
|
-
const normalized = normalizePath(path);
|
|
273
|
-
for (const entry of entries) {
|
|
274
|
-
if (entry.type === "page" && entry.path === normalized) {
|
|
275
|
-
return [{ label: getNavPageTitle(entry), path: entry.path }];
|
|
276
|
-
}
|
|
277
|
-
if (entry.type === "group") {
|
|
278
|
-
const found = entry.items.find((item) => item.path === normalized);
|
|
279
|
-
if (found) {
|
|
280
|
-
return [
|
|
281
|
-
{ label: entry.title, path: "" },
|
|
282
|
-
{ label: getNavPageTitle(found), path: found.path },
|
|
283
|
-
];
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
return [] as { label: string; path: string }[];
|
|
288
|
-
};
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import type { Tenant } from "@repo/models";
|
|
2
|
-
import { loadSiteConfig } from "@repo/previewing";
|
|
3
|
-
|
|
4
|
-
import { getTenantContentSource } from "@/lib/content-source";
|
|
5
|
-
import { getDocsCollectionWithNavigation } from "@/lib/docs-collection";
|
|
6
|
-
import { loadOpenApiRegistry } from "@/lib/openapi";
|
|
7
|
-
import { createTimedPromiseCache } from "@/lib/server-cache";
|
|
8
|
-
|
|
9
|
-
const OPENAPI_PROXY_CACHE_TTL_MS = 30 * 60 * 1000;
|
|
10
|
-
|
|
11
|
-
interface OpenApiProxyConfig {
|
|
12
|
-
allowedHosts: string[];
|
|
13
|
-
enabled: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const openApiProxyConfigCache = createTimedPromiseCache<
|
|
17
|
-
string,
|
|
18
|
-
OpenApiProxyConfig | null
|
|
19
|
-
>({
|
|
20
|
-
maxEntries: 512,
|
|
21
|
-
ttlMs: OPENAPI_PROXY_CACHE_TTL_MS,
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const getOpenApiProxyCacheKey = (tenant: Tenant) =>
|
|
25
|
-
[
|
|
26
|
-
tenant.id,
|
|
27
|
-
tenant.slug,
|
|
28
|
-
tenant.activeDeploymentId ?? "",
|
|
29
|
-
tenant.activeDeploymentManifestUrl ?? "",
|
|
30
|
-
tenant.docsPath ?? "",
|
|
31
|
-
].join(":");
|
|
32
|
-
|
|
33
|
-
const normalizeAllowedHosts = (hosts: string[]): string[] => [
|
|
34
|
-
...new Set(hosts.map((host) => host.trim().toLowerCase()).filter(Boolean)),
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
export const clearOpenApiProxyConfigCache = () => {
|
|
38
|
-
openApiProxyConfigCache.clear();
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const clearOpenApiProxyConfigCacheForTenant = (tenantId: string) => {
|
|
42
|
-
openApiProxyConfigCache.deleteByPrefix(tenantId);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export const loadOpenApiProxyConfig = async (
|
|
46
|
-
tenant: Tenant
|
|
47
|
-
): Promise<OpenApiProxyConfig | null> => {
|
|
48
|
-
const cacheKey = getOpenApiProxyCacheKey(tenant);
|
|
49
|
-
|
|
50
|
-
return await openApiProxyConfigCache.getOrCreate(cacheKey, async () => {
|
|
51
|
-
const contentSource = getTenantContentSource(tenant);
|
|
52
|
-
const configResult = await loadSiteConfig(contentSource);
|
|
53
|
-
if (!configResult.ok) {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const configuredHosts = normalizeAllowedHosts(
|
|
58
|
-
configResult.config.openapiProxy?.allowedHosts ?? []
|
|
59
|
-
);
|
|
60
|
-
if (!configResult.config.openapiProxy?.enabled || configuredHosts.length) {
|
|
61
|
-
return {
|
|
62
|
-
allowedHosts: configuredHosts,
|
|
63
|
-
enabled: configResult.config.openapiProxy?.enabled === true,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const registry = await loadOpenApiRegistry(
|
|
68
|
-
getDocsCollectionWithNavigation(configResult.config),
|
|
69
|
-
contentSource
|
|
70
|
-
);
|
|
71
|
-
const derivedHosts = normalizeAllowedHosts(
|
|
72
|
-
registry.entries.flatMap((entry) =>
|
|
73
|
-
(entry.spec.servers ?? []).flatMap((server) => {
|
|
74
|
-
try {
|
|
75
|
-
return [new URL(server.url).hostname];
|
|
76
|
-
} catch {
|
|
77
|
-
return [];
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
)
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
allowedHosts: derivedHosts,
|
|
85
|
-
enabled: true,
|
|
86
|
-
};
|
|
87
|
-
});
|
|
88
|
-
};
|
package/docs/lib/openapi.ts
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { ensureArray, normalizePath } from "@repo/common";
|
|
2
|
-
import type { CollectionConfig, DocsOpenApiSource } from "@repo/models";
|
|
3
|
-
import {
|
|
4
|
-
extractOpenApiOperations,
|
|
5
|
-
openApiIdentifier,
|
|
6
|
-
openApiSlug,
|
|
7
|
-
parseOpenApiSpec,
|
|
8
|
-
} from "@repo/prebuild";
|
|
9
|
-
import type { OpenApiOperation, OpenApiSpec } from "@repo/prebuild";
|
|
10
|
-
import { loadPrebuiltOpenApiIndex } from "@repo/previewing";
|
|
11
|
-
import type { ContentSource, PrebuiltOpenApiEntry } from "@repo/previewing";
|
|
12
|
-
|
|
13
|
-
export interface OpenApiEntry {
|
|
14
|
-
slug: string;
|
|
15
|
-
identifier: string;
|
|
16
|
-
operation: OpenApiOperation;
|
|
17
|
-
spec: OpenApiSpec;
|
|
18
|
-
source: DocsOpenApiSource;
|
|
19
|
-
sourceKey: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface OpenApiRegistry {
|
|
23
|
-
entries: OpenApiEntry[];
|
|
24
|
-
bySlug: Map<string, OpenApiEntry>;
|
|
25
|
-
byIdentifier: Map<string, OpenApiEntry>;
|
|
26
|
-
bySource: Map<string, OpenApiEntry[]>;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const toRegistry = (entries: OpenApiEntry[]): OpenApiRegistry => {
|
|
30
|
-
const bySlug = new Map<string, OpenApiEntry>();
|
|
31
|
-
const byIdentifier = new Map<string, OpenApiEntry>();
|
|
32
|
-
const bySource = new Map<string, OpenApiEntry[]>();
|
|
33
|
-
|
|
34
|
-
for (const entry of entries) {
|
|
35
|
-
bySlug.set(entry.slug, entry);
|
|
36
|
-
byIdentifier.set(entry.identifier, entry);
|
|
37
|
-
if (!bySource.has(entry.sourceKey)) {
|
|
38
|
-
bySource.set(entry.sourceKey, []);
|
|
39
|
-
}
|
|
40
|
-
bySource.get(entry.sourceKey)?.push(entry);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return { byIdentifier, bySlug, bySource, entries };
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const fromPrebuiltOpenApiEntries = (
|
|
47
|
-
entries: PrebuiltOpenApiEntry[]
|
|
48
|
-
): OpenApiRegistry => toRegistry(entries);
|
|
49
|
-
|
|
50
|
-
const getOpenApiSourceKey = (source: DocsOpenApiSource): string =>
|
|
51
|
-
`${source.source}::${source.directory ?? ""}::${(source.include ?? []).join(
|
|
52
|
-
"|"
|
|
53
|
-
)}`;
|
|
54
|
-
|
|
55
|
-
const toSourceObject = (
|
|
56
|
-
value: string | DocsOpenApiSource
|
|
57
|
-
): DocsOpenApiSource => {
|
|
58
|
-
if (typeof value === "string") {
|
|
59
|
-
return { source: value };
|
|
60
|
-
}
|
|
61
|
-
return value;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const collectOpenApiSources = (collection?: CollectionConfig) => {
|
|
65
|
-
const sources: DocsOpenApiSource[] = [];
|
|
66
|
-
|
|
67
|
-
for (const item of ensureArray(collection?.openapi)) {
|
|
68
|
-
if (!item) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
sources.push(toSourceObject(item));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const groups = collection?.navigation?.groups ?? [];
|
|
75
|
-
for (const group of groups) {
|
|
76
|
-
if (!group.openapi) {
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
sources.push(toSourceObject(group.openapi));
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const seen = new Set<string>();
|
|
83
|
-
return sources.filter((source) => {
|
|
84
|
-
const key = getOpenApiSourceKey(source);
|
|
85
|
-
if (seen.has(key)) {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
seen.add(key);
|
|
89
|
-
return true;
|
|
90
|
-
});
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
export const buildOpenApiRegistry = async (
|
|
94
|
-
collection: CollectionConfig | undefined,
|
|
95
|
-
contentSource: ContentSource
|
|
96
|
-
): Promise<OpenApiRegistry> => {
|
|
97
|
-
if (!collection || collection.type !== "docs") {
|
|
98
|
-
return toRegistry([]);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const entries: OpenApiEntry[] = [];
|
|
102
|
-
const slugPrefix = normalizePath(collection.slugPrefix ?? "");
|
|
103
|
-
|
|
104
|
-
const sources = collectOpenApiSources(collection);
|
|
105
|
-
const resolved = await Promise.all(
|
|
106
|
-
sources.map(async (source) => {
|
|
107
|
-
const rawSpec = await contentSource.readFile(source.source);
|
|
108
|
-
const spec = parseOpenApiSpec(rawSpec, source.source);
|
|
109
|
-
const directory = source.directory ?? "api";
|
|
110
|
-
const { operations } = extractOpenApiOperations(spec, directory);
|
|
111
|
-
return { directory, operations, source, spec };
|
|
112
|
-
})
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
for (const { directory, operations, source, spec } of resolved) {
|
|
116
|
-
const sourceKey = getOpenApiSourceKey(source);
|
|
117
|
-
const includeIdentifiers = source.include?.length
|
|
118
|
-
? new Set(source.include)
|
|
119
|
-
: null;
|
|
120
|
-
|
|
121
|
-
for (const operation of operations) {
|
|
122
|
-
const identifier = openApiIdentifier(operation.method, operation.path);
|
|
123
|
-
if (includeIdentifiers && !includeIdentifiers.has(identifier)) {
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const baseSlug = normalizePath(
|
|
128
|
-
openApiSlug(operation.method, operation.path, directory)
|
|
129
|
-
);
|
|
130
|
-
const slug = slugPrefix
|
|
131
|
-
? normalizePath(`${slugPrefix}/${baseSlug}`)
|
|
132
|
-
: baseSlug;
|
|
133
|
-
const entry: OpenApiEntry = {
|
|
134
|
-
identifier,
|
|
135
|
-
operation,
|
|
136
|
-
slug: normalizePath(slug),
|
|
137
|
-
source,
|
|
138
|
-
sourceKey,
|
|
139
|
-
spec,
|
|
140
|
-
};
|
|
141
|
-
entries.push(entry);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return toRegistry(entries);
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
export const loadOpenApiRegistry = async (
|
|
149
|
-
collection: CollectionConfig | undefined,
|
|
150
|
-
contentSource: ContentSource
|
|
151
|
-
): Promise<OpenApiRegistry> => {
|
|
152
|
-
const prebuilt = await loadPrebuiltOpenApiIndex(contentSource);
|
|
153
|
-
if (prebuilt) {
|
|
154
|
-
return fromPrebuiltOpenApiEntries(prebuilt);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return await buildOpenApiRegistry(collection, contentSource);
|
|
158
|
-
};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { ProjectRecord, UserRecord } from "@repo/db";
|
|
2
|
-
import { cache } from "react";
|
|
3
|
-
|
|
4
|
-
import { getDashboardSession } from "./dashboard-session";
|
|
5
|
-
import { projectDao, userDao } from "./db";
|
|
6
|
-
|
|
7
|
-
export interface AuthorizedProjectContext {
|
|
8
|
-
accessToken: string;
|
|
9
|
-
project: ProjectRecord;
|
|
10
|
-
user: UserRecord;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const resolveCurrentUser = cache(
|
|
14
|
-
async (): Promise<{
|
|
15
|
-
accessToken: string;
|
|
16
|
-
user: UserRecord;
|
|
17
|
-
} | null> => {
|
|
18
|
-
const session = await getDashboardSession();
|
|
19
|
-
if (!session) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
const user = await userDao.getByAuthId(session.authId);
|
|
23
|
-
if (!user) {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
return { accessToken: session.accessToken, user };
|
|
27
|
-
}
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
export const getAuthorizedProjectBySlug = cache(
|
|
31
|
-
async (slug: string): Promise<AuthorizedProjectContext | null> => {
|
|
32
|
-
const session = await getDashboardSession();
|
|
33
|
-
if (!session) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
const result = await projectDao.getAuthorizedBySlug(session.authId, slug);
|
|
37
|
-
if (!result) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
return {
|
|
41
|
-
accessToken: session.accessToken,
|
|
42
|
-
project: result.project,
|
|
43
|
-
user: result.user,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
);
|
package/docs/lib/routes.ts
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { normalizePath, withLeadingSlash } from "@repo/common";
|
|
2
|
-
|
|
3
|
-
const ABSOLUTE_URL_REGEX = /^[a-z][a-z\d+.-]*:/i;
|
|
4
|
-
const MARKDOWN_EXPORT_EXTENSIONS = [".md", ".mdx"] as const;
|
|
5
|
-
|
|
6
|
-
export const stripBasePath = (value: string, basePath: string) => {
|
|
7
|
-
if (!basePath) {
|
|
8
|
-
return value;
|
|
9
|
-
}
|
|
10
|
-
if (value === basePath) {
|
|
11
|
-
return "/";
|
|
12
|
-
}
|
|
13
|
-
if (value.startsWith(`${basePath}/`)) {
|
|
14
|
-
return value.slice(basePath.length) || "/";
|
|
15
|
-
}
|
|
16
|
-
return value;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const toDocHref = (path: string, basePath = "") => {
|
|
20
|
-
const clean = normalizePath(path);
|
|
21
|
-
const base = basePath ? withLeadingSlash(basePath) : "";
|
|
22
|
-
if (!clean || clean === "index") {
|
|
23
|
-
return base || "/";
|
|
24
|
-
}
|
|
25
|
-
return `${base}/${clean}`.replaceAll(/\/+/g, "/");
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const toMarkdownDocHref = (path: string, basePath = "") => {
|
|
29
|
-
const href = toDocHref(path, basePath);
|
|
30
|
-
// Index pages use /index.md, not just .md appended to the path
|
|
31
|
-
if (href === "/" || href === basePath) {
|
|
32
|
-
return `${href}/index.md`.replaceAll(/\/+/g, "/");
|
|
33
|
-
}
|
|
34
|
-
return `${href}.md`;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const getMarkdownExportSourcePath = (pathname: string) => {
|
|
38
|
-
for (const extension of MARKDOWN_EXPORT_EXTENSIONS) {
|
|
39
|
-
if (pathname.endsWith(extension)) {
|
|
40
|
-
return pathname.slice(0, -extension.length) || "/";
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return null;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export const getMarkdownExportSlug = (pathname: string, basePath = "") => {
|
|
48
|
-
const sourcePath = getMarkdownExportSourcePath(pathname);
|
|
49
|
-
if (sourcePath === null) {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const relativePath = stripBasePath(sourcePath, basePath);
|
|
54
|
-
return relativePath === "/" ? "" : relativePath.slice(1);
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export const isExternalHref = (href: string) =>
|
|
58
|
-
ABSOLUTE_URL_REGEX.test(href) || href.startsWith("//");
|
|
59
|
-
|
|
60
|
-
const isDotRelativeHref = (href: string) =>
|
|
61
|
-
href.startsWith("./") || href.startsWith("../");
|
|
62
|
-
|
|
63
|
-
const resolveDotRelativePath = (pathPart: string, currentPath: string) => {
|
|
64
|
-
const cleanCurrentPath = normalizePath(currentPath);
|
|
65
|
-
const currentDirectory = cleanCurrentPath.includes("/")
|
|
66
|
-
? cleanCurrentPath.slice(0, cleanCurrentPath.lastIndexOf("/") + 1)
|
|
67
|
-
: "";
|
|
68
|
-
const resolved = new URL(pathPart, `https://docs.local/${currentDirectory}`);
|
|
69
|
-
return normalizePath(resolved.pathname) || "index";
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
export const resolveHref = (href: string, basePath = "", currentPath = "") => {
|
|
73
|
-
if (
|
|
74
|
-
!href ||
|
|
75
|
-
href.startsWith("#") ||
|
|
76
|
-
href.startsWith("?") ||
|
|
77
|
-
isExternalHref(href)
|
|
78
|
-
) {
|
|
79
|
-
return href;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const suffixIndex = href.search(/[?#]/);
|
|
83
|
-
const pathPart = suffixIndex === -1 ? href : href.slice(0, suffixIndex);
|
|
84
|
-
const suffix = suffixIndex === -1 ? "" : href.slice(suffixIndex);
|
|
85
|
-
const resolvedPath =
|
|
86
|
-
currentPath && isDotRelativeHref(pathPart)
|
|
87
|
-
? resolveDotRelativePath(pathPart, currentPath)
|
|
88
|
-
: pathPart;
|
|
89
|
-
const normalizedBase = basePath
|
|
90
|
-
? withLeadingSlash(basePath).replaceAll(/\/+$/g, "")
|
|
91
|
-
: "";
|
|
92
|
-
const normalizedPath = withLeadingSlash(resolvedPath || "/");
|
|
93
|
-
|
|
94
|
-
if (
|
|
95
|
-
normalizedBase &&
|
|
96
|
-
(normalizedPath === normalizedBase ||
|
|
97
|
-
normalizedPath.startsWith(`${normalizedBase}/`))
|
|
98
|
-
) {
|
|
99
|
-
return `${normalizedPath}${suffix}`;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return `${toDocHref(resolvedPath || "index", basePath)}${suffix}`;
|
|
103
|
-
};
|