blodemd 0.0.10 → 0.0.12
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/README.md +11 -47
- package/dev-server/app/layout.tsx +1 -1
- package/dist/cli.mjs +1078 -406
- package/dist/cli.mjs.map +1 -1
- package/docs/app/globals.css +15 -1
- package/docs/components/api/api-playground.tsx +2 -2
- package/docs/components/docs/copy-page-menu.tsx +55 -27
- package/docs/components/docs/doc-header.tsx +1 -1
- package/docs/components/docs/doc-shell.tsx +89 -88
- package/docs/components/docs/doc-sidebar.tsx +6 -3
- package/docs/components/docs/doc-toc.tsx +1 -1
- package/docs/components/docs/mobile-nav.tsx +8 -16
- package/docs/components/docs/sidebar-scroll-area.tsx +58 -0
- package/docs/components/git/repo-picker.tsx +526 -0
- package/docs/components/mdx/agent-instructions.tsx +17 -0
- package/docs/components/mdx/code-block.tsx +6 -1
- package/docs/components/mdx/code-group.tsx +1 -1
- package/docs/components/mdx/iframe.tsx +62 -0
- package/docs/components/mdx/index.tsx +4 -0
- package/docs/components/mdx/tabs.tsx +5 -5
- package/docs/components/mdx/video.tsx +45 -12
- package/docs/components/third-parties.tsx +29 -0
- package/docs/components/ui/badge.tsx +61 -0
- package/docs/components/ui/breadcrumb.tsx +61 -41
- package/docs/components/ui/button-group.tsx +83 -0
- package/docs/components/ui/button.tsx +30 -55
- package/docs/components/ui/command.tsx +32 -4
- package/docs/components/ui/copy-button.tsx +12 -19
- package/docs/components/ui/dialog.tsx +50 -1
- package/docs/components/ui/input.tsx +16 -97
- package/docs/components/ui/kbd.tsx +98 -0
- package/docs/components/ui/morph-icon.tsx +79 -0
- package/docs/components/ui/popover.tsx +225 -30
- package/docs/components/ui/search.tsx +0 -9
- package/docs/components/ui/sheet.tsx +30 -1
- package/docs/components/ui/sidebar.tsx +332 -7
- package/docs/components/ui/site-footer.tsx +6 -4
- package/docs/components/ui/skeleton.tsx +11 -0
- package/docs/components/ui/switch.tsx +32 -0
- package/docs/components/ui/tabs.tsx +138 -0
- package/docs/lib/api-client.ts +72 -0
- package/docs/lib/contextual-options.ts +9 -0
- package/docs/lib/dashboard-session.ts +167 -0
- package/docs/lib/db.ts +13 -0
- package/docs/lib/env.ts +4 -3
- package/docs/lib/etag.ts +22 -0
- package/docs/lib/github-install.ts +33 -0
- package/docs/lib/project-authz.ts +46 -0
- package/docs/lib/routes.ts +5 -1
- package/docs/lib/supabase.ts +30 -6
- package/docs/lib/tenancy.ts +1 -0
- package/docs/lib/tenant-static.ts +206 -4
- package/docs/lib/tenants.ts +5 -1
- package/docs/lib/time-ago.ts +24 -0
- package/docs/lib/use-tab-observer.ts +71 -0
- package/package.json +2 -2
- package/packages/@repo/contracts/dist/git.d.ts +28 -0
- package/packages/@repo/contracts/dist/git.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/git.js +24 -0
- package/packages/@repo/contracts/dist/index.d.ts +1 -1
- package/packages/@repo/contracts/dist/index.d.ts.map +1 -1
- package/packages/@repo/contracts/dist/index.js +1 -1
- package/packages/@repo/contracts/src/git.ts +31 -0
- package/packages/@repo/contracts/src/index.ts +1 -1
- package/packages/@repo/models/dist/docs-config.d.ts +9 -0
- package/packages/@repo/models/dist/docs-config.d.ts.map +1 -1
- package/packages/@repo/models/dist/docs-config.js +7 -0
- package/packages/@repo/models/src/docs-config.ts +7 -0
- package/packages/@repo/previewing/dist/index.d.ts +4 -0
- package/packages/@repo/previewing/dist/index.d.ts.map +1 -1
- package/packages/@repo/previewing/dist/index.js +53 -2
- package/packages/@repo/previewing/src/index.ts +64 -2
- package/packages/@repo/validation/src/blodemd-docs-schema.json +8 -1
- package/scripts/prepare-package.mjs +14 -0
- package/packages/@repo/contracts/dist/api-key.d.ts +0 -30
- 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/src/api-key.ts +0 -27
|
@@ -31,9 +31,10 @@ import {
|
|
|
31
31
|
flattenNav,
|
|
32
32
|
getVisibleNavigation,
|
|
33
33
|
} from "@/lib/navigation";
|
|
34
|
+
import type { NavGroup } from "@/lib/navigation";
|
|
34
35
|
import type { OpenApiEntry } from "@/lib/openapi";
|
|
35
36
|
import { loadOpenApiRegistry } from "@/lib/openapi";
|
|
36
|
-
import { toDocHref } from "@/lib/routes";
|
|
37
|
+
import { toDocHref, toMarkdownDocHref } from "@/lib/routes";
|
|
37
38
|
import { createTimedPromiseCache } from "@/lib/server-cache";
|
|
38
39
|
import { getRequestProtocol } from "@/lib/tenancy";
|
|
39
40
|
import type { TenantRequestContext } from "@/lib/tenant-utility-context";
|
|
@@ -207,6 +208,7 @@ const buildTenantUrlData = async (tenant: Tenant) => {
|
|
|
207
208
|
hiddenSlugs,
|
|
208
209
|
pages: [...new Set([...navPages, ...contentPages])],
|
|
209
210
|
registry,
|
|
211
|
+
visibleNav,
|
|
210
212
|
};
|
|
211
213
|
};
|
|
212
214
|
|
|
@@ -452,7 +454,28 @@ Sitemap: ${origin}${toDocHref("sitemap.xml", basePath)}
|
|
|
452
454
|
# LLM-friendly content
|
|
453
455
|
# ${origin}${toDocHref("llms.txt", basePath)} - Index of all documentation pages
|
|
454
456
|
# ${origin}${toDocHref("llms-full.txt", basePath)} - Full documentation content
|
|
455
|
-
# Append .md to any page URL for raw markdown
|
|
457
|
+
# Append .md to any page URL for raw markdown
|
|
458
|
+
|
|
459
|
+
# Agent Skills
|
|
460
|
+
# ${origin}/.well-known/skills/index.json - Discover installable agent skills`;
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const getNavGroupSegments = (
|
|
464
|
+
data: Awaited<ReturnType<typeof loadTenantUrlData>>
|
|
465
|
+
): Map<string, Set<string>> => {
|
|
466
|
+
const segments = new Map<string, Set<string>>();
|
|
467
|
+
for (const entry of data.visibleNav) {
|
|
468
|
+
if (entry.type !== "group") {
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
const group = entry as NavGroup;
|
|
472
|
+
const segmentSlug = slugify(group.title);
|
|
473
|
+
const pageSlugs = new Set(flattenNav([group]).map((page) => page.path));
|
|
474
|
+
if (pageSlugs.size > 0) {
|
|
475
|
+
segments.set(segmentSlug, pageSlugs);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return segments;
|
|
456
479
|
};
|
|
457
480
|
|
|
458
481
|
export const buildTenantLlmsTxt = async (
|
|
@@ -467,19 +490,36 @@ export const buildTenantLlmsTxt = async (
|
|
|
467
490
|
return renderUtilityTemplate(prebuilt, tenant, context);
|
|
468
491
|
}
|
|
469
492
|
|
|
493
|
+
const urlData = await loadTenantUrlData(tenant);
|
|
470
494
|
const data = await loadTenantUtilityIndex(tenant);
|
|
471
495
|
const origin = getCanonicalOrigin(tenant, context);
|
|
472
496
|
const basePath = getCanonicalDocBasePath(tenant, context);
|
|
473
497
|
|
|
498
|
+
const segments = getNavGroupSegments(urlData);
|
|
499
|
+
const segmentLines =
|
|
500
|
+
segments.size > 0
|
|
501
|
+
? [
|
|
502
|
+
"",
|
|
503
|
+
"## Segments",
|
|
504
|
+
...[...segments.keys()].map(
|
|
505
|
+
(seg) =>
|
|
506
|
+
`- [${seg}](${origin}${toDocHref(`llms/${seg}.txt`, basePath)})`
|
|
507
|
+
),
|
|
508
|
+
]
|
|
509
|
+
: [];
|
|
510
|
+
|
|
474
511
|
const lines = [
|
|
475
512
|
`# ${data.name}`,
|
|
476
513
|
data.description ? `> ${data.description}` : null,
|
|
477
514
|
"",
|
|
478
515
|
`Sitemap: ${origin}${toDocHref("sitemap.xml", basePath)}`,
|
|
516
|
+
`Full content: ${origin}${toDocHref("llms-full.txt", basePath)}`,
|
|
517
|
+
`Skills: ${origin}/.well-known/skills/index.json`,
|
|
518
|
+
...segmentLines,
|
|
479
519
|
"",
|
|
480
520
|
"## Docs",
|
|
481
521
|
...data.pages.map((page) => {
|
|
482
|
-
const url = `${origin}${
|
|
522
|
+
const url = `${origin}${toMarkdownDocHref(page.slug, basePath)}`;
|
|
483
523
|
const desc = page.description ? `: ${page.description}` : "";
|
|
484
524
|
return `- [${page.title}](${url})${desc}`;
|
|
485
525
|
}),
|
|
@@ -521,9 +561,171 @@ export const getLlmPageText = async (tenant: Tenant, slug: string) => {
|
|
|
521
561
|
}
|
|
522
562
|
|
|
523
563
|
const data = await loadTenantUtilityIndex(tenant);
|
|
524
|
-
const page = data.pages.find(
|
|
564
|
+
const page = data.pages.find(
|
|
565
|
+
(item) => item.slug === slug || (slug === "index" && item.slug === "")
|
|
566
|
+
);
|
|
525
567
|
if (!page) {
|
|
526
568
|
return null;
|
|
527
569
|
}
|
|
528
570
|
return formatMarkdownPage(page.title, page.content);
|
|
529
571
|
};
|
|
572
|
+
|
|
573
|
+
export const buildTenantSkillsIndex = async (
|
|
574
|
+
tenant: Tenant,
|
|
575
|
+
_context: TenantRequestContext = {}
|
|
576
|
+
) => {
|
|
577
|
+
const data = await loadTenantUrlData(tenant);
|
|
578
|
+
const slug = data.config.slug ?? tenant.slug;
|
|
579
|
+
const description = data.config.description ?? "";
|
|
580
|
+
|
|
581
|
+
const skills = [
|
|
582
|
+
{
|
|
583
|
+
description: `${data.config.name} documentation. ${description}`.trim(),
|
|
584
|
+
files: ["SKILL.md"],
|
|
585
|
+
name: slug,
|
|
586
|
+
},
|
|
587
|
+
];
|
|
588
|
+
|
|
589
|
+
return JSON.stringify({ skills }, null, 2);
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
export const buildTenantSkillMd = async (
|
|
593
|
+
tenant: Tenant,
|
|
594
|
+
skillName: string,
|
|
595
|
+
context: TenantRequestContext = {}
|
|
596
|
+
) => {
|
|
597
|
+
const data = await loadTenantUrlData(tenant);
|
|
598
|
+
const slug = data.config.slug ?? tenant.slug;
|
|
599
|
+
|
|
600
|
+
if (skillName !== slug) {
|
|
601
|
+
return null;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const origin = getCanonicalOrigin(tenant, context);
|
|
605
|
+
const basePath = getCanonicalDocBasePath(tenant, context);
|
|
606
|
+
const description = data.config.description ?? "";
|
|
607
|
+
|
|
608
|
+
const lines = [
|
|
609
|
+
"---",
|
|
610
|
+
`name: ${slug}`,
|
|
611
|
+
`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(),
|
|
612
|
+
"---",
|
|
613
|
+
"",
|
|
614
|
+
`# ${data.config.name}`,
|
|
615
|
+
"",
|
|
616
|
+
description ? `${description}\n` : "",
|
|
617
|
+
"## Documentation",
|
|
618
|
+
"",
|
|
619
|
+
`- Full docs index: ${origin}${toDocHref("llms.txt", basePath)}`,
|
|
620
|
+
`- Complete docs content: ${origin}${toDocHref("llms-full.txt", basePath)}`,
|
|
621
|
+
`- Append \`.md\` to any page URL for raw markdown`,
|
|
622
|
+
"",
|
|
623
|
+
"## Key Pages",
|
|
624
|
+
"",
|
|
625
|
+
...resolveLlmPages(data)
|
|
626
|
+
.slice(0, 20)
|
|
627
|
+
.map((page) => {
|
|
628
|
+
const url = `${origin}${toMarkdownDocHref(page.slug, basePath)}`;
|
|
629
|
+
const desc = page.description ? ` - ${page.description}` : "";
|
|
630
|
+
return `- [${page.title}](${url})${desc}`;
|
|
631
|
+
}),
|
|
632
|
+
];
|
|
633
|
+
|
|
634
|
+
return lines.filter((line) => line !== null).join("\n");
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
export const buildTenantLlmsSegment = async (
|
|
638
|
+
tenant: Tenant,
|
|
639
|
+
segmentName: string,
|
|
640
|
+
context: TenantRequestContext = {}
|
|
641
|
+
): Promise<string | null> => {
|
|
642
|
+
const data = await loadTenantUrlData(tenant);
|
|
643
|
+
const segments = getNavGroupSegments(data);
|
|
644
|
+
const segmentSlugs = segments.get(segmentName);
|
|
645
|
+
if (!segmentSlugs) {
|
|
646
|
+
return null;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
const origin = getCanonicalOrigin(tenant, context);
|
|
650
|
+
const basePath = getCanonicalDocBasePath(tenant, context);
|
|
651
|
+
const utilityIndex = await loadTenantUtilityIndex(tenant);
|
|
652
|
+
|
|
653
|
+
const segmentPages = utilityIndex.pages.filter((page) =>
|
|
654
|
+
segmentSlugs.has(page.slug)
|
|
655
|
+
);
|
|
656
|
+
|
|
657
|
+
if (segmentPages.length === 0) {
|
|
658
|
+
return null;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
const groupTitle =
|
|
662
|
+
[...data.visibleNav].find(
|
|
663
|
+
(entry) => entry.type === "group" && slugify(entry.title) === segmentName
|
|
664
|
+
)?.title ?? segmentName;
|
|
665
|
+
|
|
666
|
+
const parts = segmentPages.map((page) => {
|
|
667
|
+
const url = `${origin}${toDocHref(page.slug, basePath)}`;
|
|
668
|
+
return formatMarkdownPageSection(page.title, url, page.content);
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
return [
|
|
672
|
+
`# ${data.config.name} - ${groupTitle}`,
|
|
673
|
+
`> Segment of ${origin}${toDocHref("llms-full.txt", basePath)}`,
|
|
674
|
+
"",
|
|
675
|
+
...parts,
|
|
676
|
+
].join("\n\n");
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
export const listTenantLlmsSegments = async (
|
|
680
|
+
tenant: Tenant
|
|
681
|
+
): Promise<string[]> => {
|
|
682
|
+
const data = await loadTenantUrlData(tenant);
|
|
683
|
+
return [...getNavGroupSegments(data).keys()];
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
export const getPageJson = async (
|
|
687
|
+
tenant: Tenant,
|
|
688
|
+
slug: string
|
|
689
|
+
): Promise<Record<string, unknown> | null> => {
|
|
690
|
+
const data = await loadTenantUrlData(tenant);
|
|
691
|
+
const contentEntry = data.contentIndex.bySlug.get(slug);
|
|
692
|
+
if (!contentEntry || contentEntry.kind !== "entry") {
|
|
693
|
+
return null;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
const basePath = tenant.pathPrefix ? `/${tenant.pathPrefix}` : "";
|
|
697
|
+
const url = `https://${tenant.primaryDomain}${toDocHref(slug, basePath)}`;
|
|
698
|
+
const markdownUrl = `https://${tenant.primaryDomain}${toMarkdownDocHref(slug, basePath)}`;
|
|
699
|
+
|
|
700
|
+
const result: Record<string, unknown> = {
|
|
701
|
+
"@context": "https://schema.org",
|
|
702
|
+
"@type": "TechArticle",
|
|
703
|
+
description: contentEntry.description,
|
|
704
|
+
name: contentEntry.title,
|
|
705
|
+
url,
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
if (contentEntry.frontmatter) {
|
|
709
|
+
const fm = contentEntry.frontmatter as Record<string, unknown>;
|
|
710
|
+
if (fm.price !== undefined && fm.currency !== undefined) {
|
|
711
|
+
result["@type"] = "Product";
|
|
712
|
+
result.offers = {
|
|
713
|
+
"@type": "Offer",
|
|
714
|
+
availability: "https://schema.org/InStock",
|
|
715
|
+
price: fm.price,
|
|
716
|
+
priceCurrency: fm.currency,
|
|
717
|
+
};
|
|
718
|
+
if (fm.sku) {
|
|
719
|
+
result.sku = fm.sku;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
result.encoding = {
|
|
725
|
+
"@type": "MediaObject",
|
|
726
|
+
contentUrl: markdownUrl,
|
|
727
|
+
encodingFormat: "text/markdown",
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
return result;
|
|
731
|
+
};
|
package/docs/lib/tenants.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { createTimedPromiseCache } from "./server-cache";
|
|
|
9
9
|
export const getProjectTag = (slug: string) => `project:${slug}`;
|
|
10
10
|
|
|
11
11
|
const TENANT_REVALIDATE_SECONDS = 3600;
|
|
12
|
+
const TENANT_CACHE_TTL_MS = 5 * 1000;
|
|
12
13
|
|
|
13
14
|
const mapTenant = (tenant: {
|
|
14
15
|
activeDeploymentId?: string;
|
|
@@ -29,7 +30,10 @@ const mapTenant = (tenant: {
|
|
|
29
30
|
|
|
30
31
|
const tenantCache = createTimedPromiseCache<string, Tenant | null>({
|
|
31
32
|
maxEntries: 512,
|
|
32
|
-
|
|
33
|
+
// Keep the process-local cache short. Tag/path revalidation only clears the
|
|
34
|
+
// instance that handles the request, so long-lived in-memory entries can pin
|
|
35
|
+
// warm instances to an old deployment manifest after a publish.
|
|
36
|
+
ttlMs: TENANT_CACHE_TTL_MS,
|
|
33
37
|
});
|
|
34
38
|
|
|
35
39
|
const fetchTenantFromApi = async (slug: string): Promise<Tenant | null> => {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const units: [Intl.RelativeTimeFormatUnit, number][] = [
|
|
2
|
+
["year", 31_536_000],
|
|
3
|
+
["month", 2_592_000],
|
|
4
|
+
["week", 604_800],
|
|
5
|
+
["day", 86_400],
|
|
6
|
+
["hour", 3600],
|
|
7
|
+
["minute", 60],
|
|
8
|
+
["second", 1],
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
|
|
12
|
+
|
|
13
|
+
export const timeAgo = (iso: string | null): string => {
|
|
14
|
+
if (!iso) {
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
const seconds = Math.round((Date.now() - new Date(iso).getTime()) / 1000);
|
|
18
|
+
for (const [unit, secs] of units) {
|
|
19
|
+
if (Math.abs(seconds) >= secs || unit === "second") {
|
|
20
|
+
return rtf.format(-Math.round(seconds / secs), unit);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return "";
|
|
24
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
interface TabObserverOptions {
|
|
4
|
+
onActiveTabChange?: (index: number, element: HTMLElement) => void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const useTabObserver = ({
|
|
8
|
+
onActiveTabChange,
|
|
9
|
+
}: TabObserverOptions = {}) => {
|
|
10
|
+
const listRef = React.useRef<HTMLDivElement>(null);
|
|
11
|
+
const onActiveTabChangeRef = React.useRef(onActiveTabChange);
|
|
12
|
+
|
|
13
|
+
React.useEffect(() => {
|
|
14
|
+
onActiveTabChangeRef.current = onActiveTabChange;
|
|
15
|
+
}, [onActiveTabChange]);
|
|
16
|
+
|
|
17
|
+
const handleUpdate = React.useCallback(() => {
|
|
18
|
+
if (listRef.current) {
|
|
19
|
+
const tabs = listRef.current.querySelectorAll('[role="tab"]');
|
|
20
|
+
for (let i = 0; i < tabs.length; i += 1) {
|
|
21
|
+
const el = tabs[i];
|
|
22
|
+
if (!(el instanceof HTMLElement)) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const isActive =
|
|
26
|
+
Object.hasOwn(el.dataset, "active") ||
|
|
27
|
+
el.dataset.state === "active" ||
|
|
28
|
+
el.getAttribute("aria-selected") === "true";
|
|
29
|
+
|
|
30
|
+
if (isActive) {
|
|
31
|
+
onActiveTabChangeRef.current?.(i, el);
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
const resizeObserver = new ResizeObserver(handleUpdate);
|
|
40
|
+
const mutationObserver = new MutationObserver(handleUpdate);
|
|
41
|
+
|
|
42
|
+
if (listRef.current) {
|
|
43
|
+
resizeObserver.observe(listRef.current);
|
|
44
|
+
mutationObserver.observe(listRef.current, {
|
|
45
|
+
attributes: true,
|
|
46
|
+
childList: true,
|
|
47
|
+
subtree: true,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const handleWindowUpdate = () => {
|
|
52
|
+
handleUpdate();
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
window.addEventListener("resize", handleWindowUpdate);
|
|
56
|
+
window.addEventListener("orientationchange", handleWindowUpdate);
|
|
57
|
+
document.fonts?.addEventListener?.("loadingdone", handleWindowUpdate);
|
|
58
|
+
|
|
59
|
+
handleUpdate();
|
|
60
|
+
|
|
61
|
+
return () => {
|
|
62
|
+
resizeObserver.disconnect();
|
|
63
|
+
mutationObserver.disconnect();
|
|
64
|
+
window.removeEventListener("resize", handleWindowUpdate);
|
|
65
|
+
window.removeEventListener("orientationchange", handleWindowUpdate);
|
|
66
|
+
document.fonts?.removeEventListener?.("loadingdone", handleWindowUpdate);
|
|
67
|
+
};
|
|
68
|
+
}, [handleUpdate]);
|
|
69
|
+
|
|
70
|
+
return { listRef };
|
|
71
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blodemd",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "Blode.md CLI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"@base-ui/react": "^1.3.0",
|
|
41
41
|
"@clack/prompts": "^1.0.0",
|
|
42
42
|
"@mdx-js/mdx": "^3.1.1",
|
|
43
|
-
"@repo/common": "*",
|
|
44
43
|
"@shikijs/rehype": "^4.0.2",
|
|
45
44
|
"@tailwindcss/postcss": "^4.2.2",
|
|
46
45
|
"@types/node": "^22.19.15",
|
|
@@ -74,6 +73,7 @@
|
|
|
74
73
|
"zod": "^4.3.6"
|
|
75
74
|
},
|
|
76
75
|
"devDependencies": {
|
|
76
|
+
"@repo/common": "*",
|
|
77
77
|
"@repo/previewing": "*",
|
|
78
78
|
"@repo/typescript-config": "*",
|
|
79
79
|
"oxfmt": "^0.42.0",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const GitProviderSchema: z.ZodEnum<{
|
|
3
|
+
github: "github";
|
|
4
|
+
}>;
|
|
5
|
+
export type GitProvider = z.infer<typeof GitProviderSchema>;
|
|
6
|
+
export declare const GitConnectionSchema: z.ZodObject<{
|
|
7
|
+
accountLogin: z.ZodString;
|
|
8
|
+
branch: z.ZodString;
|
|
9
|
+
createdAt: z.ZodString;
|
|
10
|
+
docsPath: z.ZodString;
|
|
11
|
+
id: z.ZodString;
|
|
12
|
+
installationId: z.ZodNumber;
|
|
13
|
+
projectId: z.ZodString;
|
|
14
|
+
provider: z.ZodEnum<{
|
|
15
|
+
github: "github";
|
|
16
|
+
}>;
|
|
17
|
+
repository: z.ZodString;
|
|
18
|
+
updatedAt: z.ZodString;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
export type GitConnection = z.infer<typeof GitConnectionSchema>;
|
|
21
|
+
export declare const GitConnectionBindSchema: z.ZodObject<{
|
|
22
|
+
branch: z.ZodDefault<z.ZodString>;
|
|
23
|
+
docsPath: z.ZodDefault<z.ZodString>;
|
|
24
|
+
installationId: z.ZodNumber;
|
|
25
|
+
repository: z.ZodString;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
export type GitConnectionBindInput = z.infer<typeof GitConnectionBindSchema>;
|
|
28
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,iBAAiB;;EAAqB,CAAC;AACpD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;iBAW9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,uBAAuB;;;;;iBAOlC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { IsoDateSchema } from "./dates.js";
|
|
3
|
+
import { IdSchema } from "./ids.js";
|
|
4
|
+
export const GitProviderSchema = z.enum(["github"]);
|
|
5
|
+
export const GitConnectionSchema = z.object({
|
|
6
|
+
accountLogin: z.string().min(1),
|
|
7
|
+
branch: z.string().min(1),
|
|
8
|
+
createdAt: IsoDateSchema,
|
|
9
|
+
docsPath: z.string().min(1),
|
|
10
|
+
id: IdSchema,
|
|
11
|
+
installationId: z.number().int().positive(),
|
|
12
|
+
projectId: IdSchema,
|
|
13
|
+
provider: GitProviderSchema,
|
|
14
|
+
repository: z.string().min(1),
|
|
15
|
+
updatedAt: IsoDateSchema,
|
|
16
|
+
});
|
|
17
|
+
export const GitConnectionBindSchema = z.object({
|
|
18
|
+
branch: z.string().min(1).default("main"),
|
|
19
|
+
docsPath: z.string().min(1).default("docs"),
|
|
20
|
+
installationId: z.number().int().positive(),
|
|
21
|
+
repository: z.string().regex(/^[\w.-]+\/[\w.-]+$/, {
|
|
22
|
+
message: "Repository must be in the format owner/repo.",
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// biome-ignore lint/performance/noBarrelFile: This is the main entry point for the package
|
|
2
2
|
// eslint-disable-next-line no-barrel-file
|
|
3
|
-
export * from "./api-key.js";
|
|
4
3
|
export * from "./dates.js";
|
|
5
4
|
export * from "./deployment.js";
|
|
6
5
|
export * from "./domain.js";
|
|
6
|
+
export * from "./git.js";
|
|
7
7
|
export * from "./ids.js";
|
|
8
8
|
export * from "./pagination.js";
|
|
9
9
|
export * from "./project.js";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { IsoDateSchema } from "./dates.js";
|
|
4
|
+
import { IdSchema } from "./ids.js";
|
|
5
|
+
|
|
6
|
+
export const GitProviderSchema = z.enum(["github"]);
|
|
7
|
+
export type GitProvider = z.infer<typeof GitProviderSchema>;
|
|
8
|
+
|
|
9
|
+
export const GitConnectionSchema = z.object({
|
|
10
|
+
accountLogin: z.string().min(1),
|
|
11
|
+
branch: z.string().min(1),
|
|
12
|
+
createdAt: IsoDateSchema,
|
|
13
|
+
docsPath: z.string().min(1),
|
|
14
|
+
id: IdSchema,
|
|
15
|
+
installationId: z.number().int().positive(),
|
|
16
|
+
projectId: IdSchema,
|
|
17
|
+
provider: GitProviderSchema,
|
|
18
|
+
repository: z.string().min(1),
|
|
19
|
+
updatedAt: IsoDateSchema,
|
|
20
|
+
});
|
|
21
|
+
export type GitConnection = z.infer<typeof GitConnectionSchema>;
|
|
22
|
+
|
|
23
|
+
export const GitConnectionBindSchema = z.object({
|
|
24
|
+
branch: z.string().min(1).default("main"),
|
|
25
|
+
docsPath: z.string().min(1).default("docs"),
|
|
26
|
+
installationId: z.number().int().positive(),
|
|
27
|
+
repository: z.string().regex(/^[\w.-]+\/[\w.-]+$/, {
|
|
28
|
+
message: "Repository must be in the format owner/repo.",
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
export type GitConnectionBindInput = z.infer<typeof GitConnectionBindSchema>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// biome-ignore lint/performance/noBarrelFile: This is the main entry point for the package
|
|
2
2
|
// eslint-disable-next-line no-barrel-file
|
|
3
|
-
export * from "./api-key.js";
|
|
4
3
|
export * from "./dates.js";
|
|
5
4
|
export * from "./deployment.js";
|
|
6
5
|
export * from "./domain.js";
|
|
6
|
+
export * from "./git.js";
|
|
7
7
|
export * from "./ids.js";
|
|
8
8
|
export * from "./pagination.js";
|
|
9
9
|
export * from "./project.js";
|
|
@@ -161,6 +161,7 @@ export declare const ContextualBuiltinOptionSchema: z.ZodEnum<{
|
|
|
161
161
|
cursor: "cursor";
|
|
162
162
|
devin: "devin";
|
|
163
163
|
"devin-mcp": "devin-mcp";
|
|
164
|
+
gemini: "gemini";
|
|
164
165
|
grok: "grok";
|
|
165
166
|
mcp: "mcp";
|
|
166
167
|
perplexity: "perplexity";
|
|
@@ -191,6 +192,7 @@ export declare const ContextualOptionSchema: z.ZodUnion<readonly [z.ZodEnum<{
|
|
|
191
192
|
cursor: "cursor";
|
|
192
193
|
devin: "devin";
|
|
193
194
|
"devin-mcp": "devin-mcp";
|
|
195
|
+
gemini: "gemini";
|
|
194
196
|
grok: "grok";
|
|
195
197
|
mcp: "mcp";
|
|
196
198
|
perplexity: "perplexity";
|
|
@@ -225,6 +227,7 @@ export declare const DocsContextualSchema: z.ZodObject<{
|
|
|
225
227
|
cursor: "cursor";
|
|
226
228
|
devin: "devin";
|
|
227
229
|
"devin-mcp": "devin-mcp";
|
|
230
|
+
gemini: "gemini";
|
|
228
231
|
grok: "grok";
|
|
229
232
|
mcp: "mcp";
|
|
230
233
|
perplexity: "perplexity";
|
|
@@ -326,6 +329,7 @@ export declare const DocsConfigSchema: z.ZodObject<{
|
|
|
326
329
|
cursor: "cursor";
|
|
327
330
|
devin: "devin";
|
|
328
331
|
"devin-mcp": "devin-mcp";
|
|
332
|
+
gemini: "gemini";
|
|
329
333
|
grok: "grok";
|
|
330
334
|
mcp: "mcp";
|
|
331
335
|
perplexity: "perplexity";
|
|
@@ -443,6 +447,7 @@ export declare const DocsConfigSchema: z.ZodObject<{
|
|
|
443
447
|
all: "all";
|
|
444
448
|
}>>;
|
|
445
449
|
}, z.core.$strict>>;
|
|
450
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
446
451
|
}, z.core.$strict>;
|
|
447
452
|
export type DocsConfig = z.infer<typeof DocsConfigSchema>;
|
|
448
453
|
export declare const MintlifyDocsConfigSchema: z.ZodObject<{
|
|
@@ -522,6 +527,7 @@ export declare const MintlifyDocsConfigSchema: z.ZodObject<{
|
|
|
522
527
|
cursor: "cursor";
|
|
523
528
|
devin: "devin";
|
|
524
529
|
"devin-mcp": "devin-mcp";
|
|
530
|
+
gemini: "gemini";
|
|
525
531
|
grok: "grok";
|
|
526
532
|
mcp: "mcp";
|
|
527
533
|
perplexity: "perplexity";
|
|
@@ -639,6 +645,7 @@ export declare const MintlifyDocsConfigSchema: z.ZodObject<{
|
|
|
639
645
|
all: "all";
|
|
640
646
|
}>>;
|
|
641
647
|
}, z.core.$strict>>;
|
|
648
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
642
649
|
}, z.core.$strict>;
|
|
643
650
|
export type MintlifyDocsConfig = DocsConfig;
|
|
644
651
|
export declare const ContentTypeSchema: z.ZodEnum<{
|
|
@@ -1020,6 +1027,7 @@ export declare const SiteConfigSchema: z.ZodObject<{
|
|
|
1020
1027
|
cursor: "cursor";
|
|
1021
1028
|
devin: "devin";
|
|
1022
1029
|
"devin-mcp": "devin-mcp";
|
|
1030
|
+
gemini: "gemini";
|
|
1023
1031
|
grok: "grok";
|
|
1024
1032
|
mcp: "mcp";
|
|
1025
1033
|
perplexity: "perplexity";
|
|
@@ -1138,6 +1146,7 @@ export declare const SiteConfigSchema: z.ZodObject<{
|
|
|
1138
1146
|
all: "all";
|
|
1139
1147
|
}>>;
|
|
1140
1148
|
}, z.core.$strict>>;
|
|
1149
|
+
slug: z.ZodOptional<z.ZodString>;
|
|
1141
1150
|
theme: z.ZodOptional<z.ZodString>;
|
|
1142
1151
|
}, z.core.$strict>;
|
|
1143
1152
|
export type SiteConfig = z.infer<typeof SiteConfigSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs-config.d.ts","sourceRoot":"","sources":["../src/docs-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"docs-config.d.ts","sourceRoot":"","sources":["../src/docs-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
const UrlOrPathSchema = z.string().min(1);
|
|
3
|
+
const SlugSchema = z
|
|
4
|
+
.string()
|
|
5
|
+
.min(1)
|
|
6
|
+
.regex(/^[a-z0-9-]+$/);
|
|
3
7
|
export const DocsColorsSchema = z
|
|
4
8
|
.object({
|
|
5
9
|
background: z.string().optional(),
|
|
@@ -317,6 +321,7 @@ export const ContextualBuiltinOptionSchema = z.enum([
|
|
|
317
321
|
"cursor",
|
|
318
322
|
"devin",
|
|
319
323
|
"devin-mcp",
|
|
324
|
+
"gemini",
|
|
320
325
|
"grok",
|
|
321
326
|
"mcp",
|
|
322
327
|
"perplexity",
|
|
@@ -370,6 +375,7 @@ export const DocsConfigSchema = z
|
|
|
370
375
|
navigation: MintlifyNavigationSchema,
|
|
371
376
|
search: MintlifySearchSchema.optional(),
|
|
372
377
|
seo: DocsSeoSchema.optional(),
|
|
378
|
+
slug: SlugSchema.optional(),
|
|
373
379
|
})
|
|
374
380
|
.strict();
|
|
375
381
|
export const MintlifyDocsConfigSchema = DocsConfigSchema;
|
|
@@ -518,6 +524,7 @@ export const SiteConfigSchema = z
|
|
|
518
524
|
openapiProxy: DocsOpenApiProxySchema.optional(),
|
|
519
525
|
scripts: DocsScriptsSchema.optional(),
|
|
520
526
|
seo: DocsSeoSchema.optional(),
|
|
527
|
+
slug: SlugSchema.optional(),
|
|
521
528
|
theme: z.string().optional(),
|
|
522
529
|
})
|
|
523
530
|
.strict();
|