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
|
@@ -1,705 +0,0 @@
|
|
|
1
|
-
import { slugify } from "@repo/common";
|
|
2
|
-
import type { TenantResolution } from "@repo/contracts";
|
|
3
|
-
import type { Tenant } from "@repo/models";
|
|
4
|
-
import type { UtilityIndex } from "@repo/previewing";
|
|
5
|
-
import {
|
|
6
|
-
absolutiseInternalLinks,
|
|
7
|
-
buildContentIndex,
|
|
8
|
-
buildPageMetadataMap,
|
|
9
|
-
formatMarkdownPage,
|
|
10
|
-
formatMarkdownPageSection,
|
|
11
|
-
formatOpenApiPageContent,
|
|
12
|
-
getPrebuiltUtilityLlmPagePath,
|
|
13
|
-
loadPrebuiltContentIndex,
|
|
14
|
-
loadPrebuiltUtilityIndex,
|
|
15
|
-
loadSiteConfig,
|
|
16
|
-
PREBUILT_UTILITY_LLMS_FULL_PATH,
|
|
17
|
-
PREBUILT_UTILITY_LLMS_PATH,
|
|
18
|
-
PREBUILT_UTILITY_LLMS_SEGMENT_PREFIX,
|
|
19
|
-
PREBUILT_UTILITY_SITEMAP_PATH,
|
|
20
|
-
prepareLlmsFullContent,
|
|
21
|
-
sanitizePlaceholderUrls,
|
|
22
|
-
stripFrontmatter,
|
|
23
|
-
toAgentMarkdown,
|
|
24
|
-
UTILITY_DOCS_ROOT_TOKEN,
|
|
25
|
-
} from "@repo/previewing";
|
|
26
|
-
|
|
27
|
-
import {
|
|
28
|
-
getTenantContentSource,
|
|
29
|
-
resolveSiteConfigAssets,
|
|
30
|
-
} from "@/lib/content-source";
|
|
31
|
-
import {
|
|
32
|
-
getDocsCollection,
|
|
33
|
-
getDocsCollectionWithNavigation,
|
|
34
|
-
getDocsNavigation,
|
|
35
|
-
} from "@/lib/docs-collection";
|
|
36
|
-
import { capLlmsFullContent } from "@/lib/llms-full";
|
|
37
|
-
import {
|
|
38
|
-
buildNavigation,
|
|
39
|
-
enrichNavWithMetadata,
|
|
40
|
-
flattenNav,
|
|
41
|
-
getVisibleNavigation,
|
|
42
|
-
} from "@/lib/navigation";
|
|
43
|
-
import type { NavGroup } from "@/lib/navigation";
|
|
44
|
-
import type { OpenApiEntry } from "@/lib/openapi";
|
|
45
|
-
import { loadOpenApiRegistry } from "@/lib/openapi";
|
|
46
|
-
import { toDocHref, toMarkdownDocHref } from "@/lib/routes";
|
|
47
|
-
import { createTimedPromiseCache } from "@/lib/server-cache";
|
|
48
|
-
import { getRequestProtocol } from "@/lib/tenancy";
|
|
49
|
-
import type { TenantRequestContext } from "@/lib/tenant-utility-context";
|
|
50
|
-
|
|
51
|
-
// Re-exported so tenant-static.unit.test.ts continues to guard the shared
|
|
52
|
-
// implementation now living in @repo/previewing.
|
|
53
|
-
export { absolutiseInternalLinks, sanitizePlaceholderUrls };
|
|
54
|
-
|
|
55
|
-
const TENANT_STATIC_CACHE_TTL_MS = 30 * 60 * 1000;
|
|
56
|
-
|
|
57
|
-
const getTenantStaticCacheKey = (tenant: Tenant) =>
|
|
58
|
-
[
|
|
59
|
-
tenant.id,
|
|
60
|
-
tenant.slug,
|
|
61
|
-
tenant.activeDeploymentId ?? "",
|
|
62
|
-
tenant.activeDeploymentManifestUrl ?? "",
|
|
63
|
-
tenant.docsPath ?? "",
|
|
64
|
-
tenant.pathPrefix ?? "",
|
|
65
|
-
tenant.primaryDomain,
|
|
66
|
-
].join(":");
|
|
67
|
-
|
|
68
|
-
const tenantUrlDataCache = createTimedPromiseCache<
|
|
69
|
-
string,
|
|
70
|
-
Awaited<ReturnType<typeof buildTenantUrlData>>
|
|
71
|
-
>({
|
|
72
|
-
maxEntries: 512,
|
|
73
|
-
ttlMs: TENANT_STATIC_CACHE_TTL_MS,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const tenantUtilityIndexCache = createTimedPromiseCache<string, UtilityIndex>({
|
|
77
|
-
maxEntries: 512,
|
|
78
|
-
ttlMs: TENANT_STATIC_CACHE_TTL_MS,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
const isMissingContentFileError = (error: unknown) => {
|
|
82
|
-
if (
|
|
83
|
-
typeof error === "object" &&
|
|
84
|
-
error !== null &&
|
|
85
|
-
"code" in error &&
|
|
86
|
-
(error as { code?: string }).code === "ENOENT"
|
|
87
|
-
) {
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return error instanceof Error && error.message.includes("not found");
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const getCanonicalHost = (
|
|
95
|
-
tenant: Tenant,
|
|
96
|
-
requestedHost?: string,
|
|
97
|
-
strategy?: TenantResolution["strategy"] | null
|
|
98
|
-
) =>
|
|
99
|
-
(strategy === "custom-domain" || strategy === "path") && requestedHost
|
|
100
|
-
? requestedHost
|
|
101
|
-
: tenant.primaryDomain;
|
|
102
|
-
|
|
103
|
-
const getCanonicalBasePath = (
|
|
104
|
-
tenant: Tenant,
|
|
105
|
-
basePath?: string,
|
|
106
|
-
strategy?: TenantResolution["strategy"] | null
|
|
107
|
-
) => {
|
|
108
|
-
if (strategy === "path") {
|
|
109
|
-
return basePath || `/${tenant.slug}`;
|
|
110
|
-
}
|
|
111
|
-
if (strategy === "custom-domain") {
|
|
112
|
-
return basePath ?? tenant.pathPrefix ?? "";
|
|
113
|
-
}
|
|
114
|
-
return basePath ?? "";
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
export const getTenantRequestContextFromHeaders = (
|
|
118
|
-
tenant: Tenant,
|
|
119
|
-
headerStore: Pick<Headers, "get">
|
|
120
|
-
): TenantRequestContext => ({
|
|
121
|
-
basePath: headerStore.get("x-tenant-base-path") ?? tenant.pathPrefix ?? "",
|
|
122
|
-
protocol: getRequestProtocol(headerStore),
|
|
123
|
-
requestedHost: headerStore.get("x-tenant-domain") ?? undefined,
|
|
124
|
-
strategy: (headerStore.get("x-tenant-strategy") ?? null) as
|
|
125
|
-
| TenantResolution["strategy"]
|
|
126
|
-
| null,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
export const getStaticTenantRequestContext = (
|
|
130
|
-
tenant: Tenant
|
|
131
|
-
): TenantRequestContext => ({
|
|
132
|
-
basePath: tenant.pathPrefix ?? "",
|
|
133
|
-
protocol: "https",
|
|
134
|
-
requestedHost: tenant.primaryDomain,
|
|
135
|
-
strategy: tenant.customDomains.length > 0 ? "custom-domain" : null,
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
export const getCanonicalOrigin = (
|
|
139
|
-
tenant: Tenant,
|
|
140
|
-
context: TenantRequestContext = {}
|
|
141
|
-
) =>
|
|
142
|
-
`${context.protocol ?? "https"}://${getCanonicalHost(
|
|
143
|
-
tenant,
|
|
144
|
-
context.requestedHost,
|
|
145
|
-
context.strategy
|
|
146
|
-
)}`;
|
|
147
|
-
|
|
148
|
-
export const getCanonicalDocBasePath = (
|
|
149
|
-
tenant: Tenant,
|
|
150
|
-
context: TenantRequestContext = {}
|
|
151
|
-
) => getCanonicalBasePath(tenant, context.basePath, context.strategy);
|
|
152
|
-
|
|
153
|
-
const renderUtilityTemplate = (
|
|
154
|
-
source: string,
|
|
155
|
-
tenant: Tenant,
|
|
156
|
-
context: TenantRequestContext = {}
|
|
157
|
-
) =>
|
|
158
|
-
source.replaceAll(
|
|
159
|
-
UTILITY_DOCS_ROOT_TOKEN,
|
|
160
|
-
`${getCanonicalOrigin(tenant, context)}${getCanonicalDocBasePath(
|
|
161
|
-
tenant,
|
|
162
|
-
context
|
|
163
|
-
)}`
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
const buildTenantUrlData = async (tenant: Tenant) => {
|
|
167
|
-
const contentSource = getTenantContentSource(tenant);
|
|
168
|
-
const configResult = await loadSiteConfig(contentSource);
|
|
169
|
-
if (!configResult.ok) {
|
|
170
|
-
throw new Error("Invalid config");
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const config = await resolveSiteConfigAssets(
|
|
174
|
-
configResult.config,
|
|
175
|
-
contentSource
|
|
176
|
-
);
|
|
177
|
-
const contentIndex =
|
|
178
|
-
(await loadPrebuiltContentIndex(contentSource)) ??
|
|
179
|
-
(await buildContentIndex(contentSource, config));
|
|
180
|
-
if (contentIndex.errors.length) {
|
|
181
|
-
throw new Error("Invalid content");
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const docsCollection = getDocsCollection(config);
|
|
185
|
-
const docsNavigation = getDocsNavigation(config);
|
|
186
|
-
const docsCollectionWithNavigation = getDocsCollectionWithNavigation(config);
|
|
187
|
-
const registry = await loadOpenApiRegistry(
|
|
188
|
-
docsCollectionWithNavigation,
|
|
189
|
-
contentSource
|
|
190
|
-
);
|
|
191
|
-
const metadataMap = buildPageMetadataMap(contentIndex);
|
|
192
|
-
const rawNav = docsNavigation
|
|
193
|
-
? buildNavigation(
|
|
194
|
-
docsNavigation,
|
|
195
|
-
registry,
|
|
196
|
-
docsCollection?.slugPrefix ?? ""
|
|
197
|
-
)
|
|
198
|
-
: [];
|
|
199
|
-
const nav = enrichNavWithMetadata(rawNav, metadataMap);
|
|
200
|
-
const visibleNav = getVisibleNavigation(nav);
|
|
201
|
-
const hiddenSlugs = new Set<string>();
|
|
202
|
-
for (const [slug, meta] of metadataMap) {
|
|
203
|
-
if (meta.hidden || meta.noindex) {
|
|
204
|
-
hiddenSlugs.add(slug);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
const navPages = flattenNav(visibleNav).map((page) => page.path);
|
|
209
|
-
const contentPages = contentIndex.entries
|
|
210
|
-
.filter(
|
|
211
|
-
(entry) =>
|
|
212
|
-
!(entry.kind === "entry" && entry.hidden) &&
|
|
213
|
-
!hiddenSlugs.has(entry.slug)
|
|
214
|
-
)
|
|
215
|
-
.map((entry) => entry.slug);
|
|
216
|
-
|
|
217
|
-
return {
|
|
218
|
-
config,
|
|
219
|
-
contentIndex,
|
|
220
|
-
contentSource,
|
|
221
|
-
hiddenSlugs,
|
|
222
|
-
pages: [...new Set([...navPages, ...contentPages])],
|
|
223
|
-
registry,
|
|
224
|
-
visibleNav,
|
|
225
|
-
};
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
const loadTenantUrlData = async (tenant: Tenant) =>
|
|
229
|
-
await tenantUrlDataCache.getOrCreate(
|
|
230
|
-
getTenantStaticCacheKey(tenant),
|
|
231
|
-
async () => await buildTenantUrlData(tenant)
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
const resolveLlmPages = (
|
|
235
|
-
data: Awaited<ReturnType<typeof loadTenantUrlData>>
|
|
236
|
-
): (
|
|
237
|
-
| {
|
|
238
|
-
kind: "content";
|
|
239
|
-
relativePath: string;
|
|
240
|
-
slug: string;
|
|
241
|
-
title: string;
|
|
242
|
-
description?: string;
|
|
243
|
-
}
|
|
244
|
-
| {
|
|
245
|
-
kind: "openapi";
|
|
246
|
-
entry: OpenApiEntry;
|
|
247
|
-
slug: string;
|
|
248
|
-
title: string;
|
|
249
|
-
description?: string;
|
|
250
|
-
}
|
|
251
|
-
)[] =>
|
|
252
|
-
data.pages
|
|
253
|
-
.map((slug) => {
|
|
254
|
-
const contentEntry = data.contentIndex.bySlug.get(slug);
|
|
255
|
-
if (
|
|
256
|
-
contentEntry &&
|
|
257
|
-
contentEntry.kind === "entry" &&
|
|
258
|
-
!contentEntry.hidden &&
|
|
259
|
-
!data.hiddenSlugs.has(contentEntry.slug)
|
|
260
|
-
) {
|
|
261
|
-
return {
|
|
262
|
-
description: contentEntry.description,
|
|
263
|
-
kind: "content" as const,
|
|
264
|
-
relativePath: contentEntry.relativePath,
|
|
265
|
-
slug: contentEntry.slug,
|
|
266
|
-
title: contentEntry.title,
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
const openApiEntry = data.registry.bySlug.get(slug);
|
|
271
|
-
if (!openApiEntry) {
|
|
272
|
-
return null;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
return {
|
|
276
|
-
description: openApiEntry.operation.description,
|
|
277
|
-
entry: openApiEntry,
|
|
278
|
-
kind: "openapi" as const,
|
|
279
|
-
slug,
|
|
280
|
-
title: openApiEntry.operation.summary ?? openApiEntry.identifier,
|
|
281
|
-
};
|
|
282
|
-
})
|
|
283
|
-
.filter((page) => page !== null);
|
|
284
|
-
|
|
285
|
-
const buildRuntimeUtilityIndex = async (
|
|
286
|
-
tenant: Tenant
|
|
287
|
-
): Promise<UtilityIndex> => {
|
|
288
|
-
const data = await loadTenantUrlData(tenant);
|
|
289
|
-
const pages = await Promise.all(
|
|
290
|
-
resolveLlmPages(data).map(async (page) => {
|
|
291
|
-
if (page.kind === "openapi") {
|
|
292
|
-
return {
|
|
293
|
-
content: formatOpenApiPageContent(page.entry.operation),
|
|
294
|
-
description: page.description,
|
|
295
|
-
slug: page.slug,
|
|
296
|
-
title: page.title,
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
const raw = await data.contentSource.readFile(page.relativePath);
|
|
301
|
-
return {
|
|
302
|
-
content: toAgentMarkdown(stripFrontmatter(raw)),
|
|
303
|
-
description: page.description,
|
|
304
|
-
slug: page.slug,
|
|
305
|
-
title: page.title,
|
|
306
|
-
};
|
|
307
|
-
})
|
|
308
|
-
);
|
|
309
|
-
|
|
310
|
-
return {
|
|
311
|
-
description: data.config.description,
|
|
312
|
-
name: data.config.name,
|
|
313
|
-
pages,
|
|
314
|
-
};
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
export const loadTenantUtilityIndex = async (tenant: Tenant) =>
|
|
318
|
-
await tenantUtilityIndexCache.getOrCreate(
|
|
319
|
-
getTenantStaticCacheKey(tenant),
|
|
320
|
-
async () => {
|
|
321
|
-
const prebuilt = await loadPrebuiltUtilityIndex(
|
|
322
|
-
getTenantContentSource(tenant)
|
|
323
|
-
);
|
|
324
|
-
if (prebuilt) {
|
|
325
|
-
return prebuilt;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
return await buildRuntimeUtilityIndex(tenant);
|
|
329
|
-
}
|
|
330
|
-
);
|
|
331
|
-
|
|
332
|
-
const loadTenantUtilityTemplate = async (tenant: Tenant, path: string) => {
|
|
333
|
-
const contentSource = getTenantContentSource(tenant);
|
|
334
|
-
try {
|
|
335
|
-
return await contentSource.readFile(path);
|
|
336
|
-
} catch (error) {
|
|
337
|
-
if (isMissingContentFileError(error)) {
|
|
338
|
-
return null;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
throw error;
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
export const clearTenantStaticCaches = () => {
|
|
346
|
-
tenantUrlDataCache.clear();
|
|
347
|
-
tenantUtilityIndexCache.clear();
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
export const clearTenantStaticCachesForTenant = (tenantId: string) => {
|
|
351
|
-
tenantUrlDataCache.deleteByPrefix(tenantId);
|
|
352
|
-
tenantUtilityIndexCache.deleteByPrefix(tenantId);
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
export const buildTenantSitemapXml = async (
|
|
356
|
-
tenant: Tenant,
|
|
357
|
-
context: TenantRequestContext = {}
|
|
358
|
-
) => {
|
|
359
|
-
const prebuilt = await loadTenantUtilityTemplate(
|
|
360
|
-
tenant,
|
|
361
|
-
PREBUILT_UTILITY_SITEMAP_PATH
|
|
362
|
-
);
|
|
363
|
-
if (prebuilt) {
|
|
364
|
-
return renderUtilityTemplate(prebuilt, tenant, context);
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
const { pages } = await loadTenantUtilityIndex(tenant);
|
|
368
|
-
const origin = getCanonicalOrigin(tenant, context);
|
|
369
|
-
const basePath = getCanonicalDocBasePath(tenant, context);
|
|
370
|
-
const urls = pages.map(
|
|
371
|
-
(page) => `${origin}${toDocHref(page.slug, basePath)}`
|
|
372
|
-
);
|
|
373
|
-
|
|
374
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
375
|
-
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
376
|
-
${urls.map((url) => ` <url><loc>${url}</loc></url>`).join("\n")}
|
|
377
|
-
</urlset>`;
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
export const buildTenantRobotsTxt = (
|
|
381
|
-
tenant: Tenant,
|
|
382
|
-
context: TenantRequestContext = {}
|
|
383
|
-
) => {
|
|
384
|
-
const origin = getCanonicalOrigin(tenant, context);
|
|
385
|
-
const basePath = getCanonicalDocBasePath(tenant, context);
|
|
386
|
-
return `User-agent: *
|
|
387
|
-
Allow: /
|
|
388
|
-
Content-Signal: ai-train=no, search=yes, ai-input=yes
|
|
389
|
-
|
|
390
|
-
# LLM-friendly content
|
|
391
|
-
# Append .md to any page URL for raw markdown
|
|
392
|
-
# ${origin}${toDocHref("llms-full.txt", basePath)} - Full documentation content
|
|
393
|
-
# ${origin}${toDocHref("llms.txt", basePath)} - Index of all documentation pages
|
|
394
|
-
|
|
395
|
-
Sitemap: ${origin}${toDocHref("sitemap.xml", basePath)}
|
|
396
|
-
|
|
397
|
-
# Agent Skills
|
|
398
|
-
# ${origin}${toDocHref(".well-known/skills/index.json", basePath)} - Discover installable agent skills`;
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
const getNavGroupSegments = (
|
|
402
|
-
data: Awaited<ReturnType<typeof loadTenantUrlData>>
|
|
403
|
-
): Map<string, Set<string>> => {
|
|
404
|
-
const segments = new Map<string, Set<string>>();
|
|
405
|
-
for (const entry of data.visibleNav) {
|
|
406
|
-
if (entry.type !== "group") {
|
|
407
|
-
continue;
|
|
408
|
-
}
|
|
409
|
-
const group = entry as NavGroup;
|
|
410
|
-
const segmentSlug = slugify(group.title);
|
|
411
|
-
const pageSlugs = new Set(flattenNav([group]).map((page) => page.path));
|
|
412
|
-
if (pageSlugs.size > 0) {
|
|
413
|
-
segments.set(segmentSlug, pageSlugs);
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
return segments;
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
export const buildTenantLlmsTxt = async (
|
|
420
|
-
tenant: Tenant,
|
|
421
|
-
context: TenantRequestContext = {}
|
|
422
|
-
) => {
|
|
423
|
-
const prebuilt = await loadTenantUtilityTemplate(
|
|
424
|
-
tenant,
|
|
425
|
-
PREBUILT_UTILITY_LLMS_PATH
|
|
426
|
-
);
|
|
427
|
-
if (prebuilt) {
|
|
428
|
-
return renderUtilityTemplate(prebuilt, tenant, context);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
const urlData = await loadTenantUrlData(tenant);
|
|
432
|
-
const data = await loadTenantUtilityIndex(tenant);
|
|
433
|
-
const origin = getCanonicalOrigin(tenant, context);
|
|
434
|
-
const basePath = getCanonicalDocBasePath(tenant, context);
|
|
435
|
-
|
|
436
|
-
const segments = getNavGroupSegments(urlData);
|
|
437
|
-
const segmentLines =
|
|
438
|
-
segments.size > 0
|
|
439
|
-
? [
|
|
440
|
-
"",
|
|
441
|
-
"## Segments",
|
|
442
|
-
...[...segments.keys()].map(
|
|
443
|
-
(seg) =>
|
|
444
|
-
`- [${seg}](${origin}${toDocHref(`llms/${seg}.txt`, basePath)})`
|
|
445
|
-
),
|
|
446
|
-
]
|
|
447
|
-
: [];
|
|
448
|
-
|
|
449
|
-
const lines = [
|
|
450
|
-
`# ${data.name}`,
|
|
451
|
-
data.description ? `> ${data.description}` : null,
|
|
452
|
-
"",
|
|
453
|
-
`Sitemap: ${origin}${toDocHref("sitemap.xml", basePath)}`,
|
|
454
|
-
`Full content: ${origin}${toDocHref("llms-full.txt", basePath)}`,
|
|
455
|
-
`Skills: ${origin}${toDocHref(".well-known/skills/index.json", basePath)}`,
|
|
456
|
-
...segmentLines,
|
|
457
|
-
"",
|
|
458
|
-
"## Docs",
|
|
459
|
-
...data.pages.map((page) => {
|
|
460
|
-
const url = `${origin}${toMarkdownDocHref(page.slug, basePath)}`;
|
|
461
|
-
const desc = page.description ? `: ${page.description}` : "";
|
|
462
|
-
return `- [${page.title}](${url})${desc}`;
|
|
463
|
-
}),
|
|
464
|
-
];
|
|
465
|
-
|
|
466
|
-
return lines.filter((line) => line !== null).join("\n");
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
export const buildTenantLlmsFullTxt = async (
|
|
470
|
-
tenant: Tenant,
|
|
471
|
-
context: TenantRequestContext = {}
|
|
472
|
-
) => {
|
|
473
|
-
const origin = getCanonicalOrigin(tenant, context);
|
|
474
|
-
const basePath = getCanonicalDocBasePath(tenant, context);
|
|
475
|
-
const indexUrl = `${origin}${toDocHref("llms.txt", basePath)}`;
|
|
476
|
-
|
|
477
|
-
const prebuilt = await loadTenantUtilityTemplate(
|
|
478
|
-
tenant,
|
|
479
|
-
PREBUILT_UTILITY_LLMS_FULL_PATH
|
|
480
|
-
);
|
|
481
|
-
if (prebuilt) {
|
|
482
|
-
const rendered = renderUtilityTemplate(prebuilt, tenant, context);
|
|
483
|
-
return capLlmsFullContent(
|
|
484
|
-
prepareLlmsFullContent(rendered, origin, basePath),
|
|
485
|
-
indexUrl
|
|
486
|
-
);
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
const data = await loadTenantUtilityIndex(tenant);
|
|
490
|
-
const parts = data.pages.map((page) => {
|
|
491
|
-
const url = `${origin}${toDocHref(page.slug, basePath)}`;
|
|
492
|
-
const content = prepareLlmsFullContent(page.content, origin, basePath);
|
|
493
|
-
return formatMarkdownPageSection(
|
|
494
|
-
page.title,
|
|
495
|
-
url,
|
|
496
|
-
content,
|
|
497
|
-
page.description
|
|
498
|
-
);
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
return capLlmsFullContent(parts.join("\n\n"), indexUrl);
|
|
502
|
-
};
|
|
503
|
-
|
|
504
|
-
export const getLlmPageText = async (
|
|
505
|
-
tenant: Tenant,
|
|
506
|
-
slug: string,
|
|
507
|
-
_context: TenantRequestContext = {}
|
|
508
|
-
) => {
|
|
509
|
-
const prebuilt = await loadTenantUtilityTemplate(
|
|
510
|
-
tenant,
|
|
511
|
-
getPrebuiltUtilityLlmPagePath(slug)
|
|
512
|
-
);
|
|
513
|
-
if (prebuilt) {
|
|
514
|
-
return prebuilt;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
const data = await loadTenantUtilityIndex(tenant);
|
|
518
|
-
const page = data.pages.find(
|
|
519
|
-
(item) => item.slug === slug || (slug === "index" && item.slug === "")
|
|
520
|
-
);
|
|
521
|
-
if (!page) {
|
|
522
|
-
return null;
|
|
523
|
-
}
|
|
524
|
-
return formatMarkdownPage(
|
|
525
|
-
page.title,
|
|
526
|
-
toAgentMarkdown(page.content),
|
|
527
|
-
page.description
|
|
528
|
-
);
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
export const buildTenantSkillsIndex = async (
|
|
532
|
-
tenant: Tenant,
|
|
533
|
-
_context: TenantRequestContext = {}
|
|
534
|
-
) => {
|
|
535
|
-
const data = await loadTenantUrlData(tenant);
|
|
536
|
-
const slug = data.config.slug ?? tenant.slug;
|
|
537
|
-
const description = data.config.description ?? "";
|
|
538
|
-
|
|
539
|
-
const skills = [
|
|
540
|
-
{
|
|
541
|
-
description: `${data.config.name} documentation. ${description}`.trim(),
|
|
542
|
-
files: ["SKILL.md"],
|
|
543
|
-
name: slug,
|
|
544
|
-
},
|
|
545
|
-
];
|
|
546
|
-
|
|
547
|
-
return JSON.stringify({ skills }, null, 2);
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
export const buildTenantSkillMd = async (
|
|
551
|
-
tenant: Tenant,
|
|
552
|
-
skillName: string,
|
|
553
|
-
context: TenantRequestContext = {}
|
|
554
|
-
) => {
|
|
555
|
-
const data = await loadTenantUrlData(tenant);
|
|
556
|
-
const slug = data.config.slug ?? tenant.slug;
|
|
557
|
-
|
|
558
|
-
if (skillName !== slug) {
|
|
559
|
-
return null;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
const origin = getCanonicalOrigin(tenant, context);
|
|
563
|
-
const basePath = getCanonicalDocBasePath(tenant, context);
|
|
564
|
-
const description = data.config.description ?? "";
|
|
565
|
-
|
|
566
|
-
const lines = [
|
|
567
|
-
"---",
|
|
568
|
-
`name: ${slug}`,
|
|
569
|
-
`description: ${data.config.name} documentation. ${description} Use when working with ${data.config.name}, answering questions about its features, or helping users follow its guides.`.trim(),
|
|
570
|
-
"---",
|
|
571
|
-
"",
|
|
572
|
-
`# ${data.config.name}`,
|
|
573
|
-
"",
|
|
574
|
-
description ? `${description}\n` : "",
|
|
575
|
-
"## Documentation",
|
|
576
|
-
"",
|
|
577
|
-
`- Full docs index: ${origin}${toDocHref("llms.txt", basePath)}`,
|
|
578
|
-
`- Complete docs content: ${origin}${toDocHref("llms-full.txt", basePath)}`,
|
|
579
|
-
`- Append \`.md\` to any page URL for raw markdown`,
|
|
580
|
-
"",
|
|
581
|
-
"## Key Pages",
|
|
582
|
-
"",
|
|
583
|
-
...resolveLlmPages(data)
|
|
584
|
-
.slice(0, 20)
|
|
585
|
-
.map((page) => {
|
|
586
|
-
const url = `${origin}${toMarkdownDocHref(page.slug, basePath)}`;
|
|
587
|
-
const desc = page.description ? ` - ${page.description}` : "";
|
|
588
|
-
return `- [${page.title}](${url})${desc}`;
|
|
589
|
-
}),
|
|
590
|
-
];
|
|
591
|
-
|
|
592
|
-
return lines.filter((line) => line !== null).join("\n");
|
|
593
|
-
};
|
|
594
|
-
|
|
595
|
-
export const buildTenantLlmsSegment = async (
|
|
596
|
-
tenant: Tenant,
|
|
597
|
-
segmentName: string,
|
|
598
|
-
context: TenantRequestContext = {}
|
|
599
|
-
): Promise<string | null> => {
|
|
600
|
-
const prebuilt = await loadTenantUtilityTemplate(
|
|
601
|
-
tenant,
|
|
602
|
-
`${PREBUILT_UTILITY_LLMS_SEGMENT_PREFIX}${segmentName}.txt`
|
|
603
|
-
);
|
|
604
|
-
if (prebuilt) {
|
|
605
|
-
return renderUtilityTemplate(prebuilt, tenant, context);
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
const data = await loadTenantUrlData(tenant);
|
|
609
|
-
const segments = getNavGroupSegments(data);
|
|
610
|
-
const segmentSlugs = segments.get(segmentName);
|
|
611
|
-
if (!segmentSlugs) {
|
|
612
|
-
return null;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
const origin = getCanonicalOrigin(tenant, context);
|
|
616
|
-
const basePath = getCanonicalDocBasePath(tenant, context);
|
|
617
|
-
const utilityIndex = await loadTenantUtilityIndex(tenant);
|
|
618
|
-
|
|
619
|
-
const segmentPages = utilityIndex.pages.filter((page) =>
|
|
620
|
-
segmentSlugs.has(page.slug)
|
|
621
|
-
);
|
|
622
|
-
|
|
623
|
-
if (segmentPages.length === 0) {
|
|
624
|
-
return null;
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
const groupTitle =
|
|
628
|
-
[...data.visibleNav].find(
|
|
629
|
-
(entry) => entry.type === "group" && slugify(entry.title) === segmentName
|
|
630
|
-
)?.title ?? segmentName;
|
|
631
|
-
|
|
632
|
-
const parts = segmentPages.map((page) => {
|
|
633
|
-
const url = `${origin}${toDocHref(page.slug, basePath)}`;
|
|
634
|
-
const content = prepareLlmsFullContent(page.content, origin, basePath);
|
|
635
|
-
return formatMarkdownPageSection(
|
|
636
|
-
page.title,
|
|
637
|
-
url,
|
|
638
|
-
content,
|
|
639
|
-
page.description
|
|
640
|
-
);
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
return [
|
|
644
|
-
`# ${data.config.name} - ${groupTitle}`,
|
|
645
|
-
`> Segment of ${origin}${toDocHref("llms-full.txt", basePath)}`,
|
|
646
|
-
"",
|
|
647
|
-
...parts,
|
|
648
|
-
].join("\n\n");
|
|
649
|
-
};
|
|
650
|
-
|
|
651
|
-
export const listTenantLlmsSegments = async (
|
|
652
|
-
tenant: Tenant
|
|
653
|
-
): Promise<string[]> => {
|
|
654
|
-
const data = await loadTenantUrlData(tenant);
|
|
655
|
-
return [...getNavGroupSegments(data).keys()];
|
|
656
|
-
};
|
|
657
|
-
|
|
658
|
-
export const getPageJson = async (
|
|
659
|
-
tenant: Tenant,
|
|
660
|
-
slug: string,
|
|
661
|
-
context: TenantRequestContext = {}
|
|
662
|
-
): Promise<Record<string, unknown> | null> => {
|
|
663
|
-
const data = await loadTenantUrlData(tenant);
|
|
664
|
-
const contentEntry = data.contentIndex.bySlug.get(slug);
|
|
665
|
-
if (!contentEntry || contentEntry.kind !== "entry") {
|
|
666
|
-
return null;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
const origin = getCanonicalOrigin(tenant, context);
|
|
670
|
-
const basePath = getCanonicalDocBasePath(tenant, context);
|
|
671
|
-
const url = `${origin}${toDocHref(slug, basePath)}`;
|
|
672
|
-
const markdownUrl = `${origin}${toMarkdownDocHref(slug, basePath)}`;
|
|
673
|
-
|
|
674
|
-
const result: Record<string, unknown> = {
|
|
675
|
-
"@context": "https://schema.org",
|
|
676
|
-
"@type": "TechArticle",
|
|
677
|
-
description: contentEntry.description,
|
|
678
|
-
name: contentEntry.title,
|
|
679
|
-
url,
|
|
680
|
-
};
|
|
681
|
-
|
|
682
|
-
if (contentEntry.frontmatter) {
|
|
683
|
-
const fm = contentEntry.frontmatter as Record<string, unknown>;
|
|
684
|
-
if (fm.price !== undefined && fm.currency !== undefined) {
|
|
685
|
-
result["@type"] = "Product";
|
|
686
|
-
result.offers = {
|
|
687
|
-
"@type": "Offer",
|
|
688
|
-
availability: "https://schema.org/InStock",
|
|
689
|
-
price: fm.price,
|
|
690
|
-
priceCurrency: fm.currency,
|
|
691
|
-
};
|
|
692
|
-
if (fm.sku) {
|
|
693
|
-
result.sku = fm.sku;
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
result.encoding = {
|
|
699
|
-
"@type": "MediaObject",
|
|
700
|
-
contentUrl: markdownUrl,
|
|
701
|
-
encodingFormat: "text/markdown",
|
|
702
|
-
};
|
|
703
|
-
|
|
704
|
-
return result;
|
|
705
|
-
};
|