deepspace 0.10.2 → 0.11.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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # deepspace
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Replace the base64 deploy asset transport with a content-addressed one. The CLI now hashes the build output locally, asks the platform which files it is missing, and streams only those into the app's release store; unchanged files are never re-uploaded, and no deploy ever serializes its assets into a JSON payload. This removes the "Worker exceeded memory limit" failure that surfaced as a misleading Cloudflare-incident 503 on asset-heavy deploys, and a deploy-service resource limit is now reported distinctly from a genuine Cloudflare API incident.
8
+
9
+ **This release requires an updated deploy service and is required to deploy.** The old grouped-upload endpoints are gone: an older CLI is answered with a clear "update to deploy" instruction, and this CLI refuses to start against a deploy service that does not advertise the new transport. Releases recorded before the cutover can no longer be rolled back to directly — redeploy that commit instead.
10
+
11
+ ## 0.10.3
12
+
13
+ ### Patch Changes
14
+
15
+ - Documentation polish: Mintlify-parity UI pass (self-hosted fonts, type scale, sticky launcher, docked assistant, accessible syntax palette, heading-level search), navigation no longer fades over the assistant, MDX imports honor tsconfig path aliases, deploy quota errors name the apps holding slots, scaffolds install with the invoking package manager, and the retired community library publish command is removed.
16
+
3
17
  ## 0.10.2
4
18
 
5
19
  ### Patch Changes
@@ -12,6 +12,7 @@ import {
12
12
  useRef as useRef2,
13
13
  useState as useState2
14
14
  } from "react";
15
+ import { createPortal } from "react-dom";
15
16
 
16
17
  // src/documentation/types.ts
17
18
  var DocumentationError = class extends Error {
@@ -237,6 +238,12 @@ function SendIcon(props) {
237
238
  function StopIcon(props) {
238
239
  return /* @__PURE__ */ jsx(Icon, { ...props, children: /* @__PURE__ */ jsx("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2", fill: "currentColor" }) });
239
240
  }
241
+ function HashIcon(props) {
242
+ return /* @__PURE__ */ jsx(Icon, { ...props, children: /* @__PURE__ */ jsx("path", { d: "M9.5 4 7.5 20M16.5 4l-2 16M4.5 9h15M3.5 15h15", stroke: "currentColor", strokeLinecap: "round", strokeWidth: "1.6" }) });
243
+ }
244
+ function ListIcon(props) {
245
+ return /* @__PURE__ */ jsx(Icon, { ...props, children: /* @__PURE__ */ jsx("path", { d: "M4 6h16M4 12h11M4 18h7", stroke: "currentColor", strokeLinecap: "round", strokeWidth: "1.8" }) });
246
+ }
240
247
 
241
248
  // src/documentation/runtime/page-actions.tsx
242
249
  import { useEffect, useRef, useState } from "react";
@@ -372,13 +379,15 @@ function PageActions({
372
379
  }
373
380
 
374
381
  // src/documentation/runtime/article.tsx
375
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
382
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
376
383
  function Article({
377
384
  children,
378
385
  data,
386
+ launcher,
379
387
  onAssistantOpen
380
388
  }) {
381
389
  const articleRef = useRef2(null);
390
+ const codeBlocks = useCodeBlockMounts(articleRef, data.page.route);
382
391
  useArticleEnhancements(articleRef, data, onAssistantOpen);
383
392
  return /* @__PURE__ */ jsxs3("article", { className: "documentation-article", ref: articleRef, children: [
384
393
  /* @__PURE__ */ jsx3(Breadcrumbs, { items: data.breadcrumbs }),
@@ -390,8 +399,24 @@ function Article({
390
399
  /* @__PURE__ */ jsx3("h1", { children: data.page.title }),
391
400
  data.page.description && /* @__PURE__ */ jsx3("p", { className: "documentation-lede", children: data.page.description })
392
401
  ] }),
402
+ /* @__PURE__ */ jsx3(OutlineDisclosure, { headings: outlineHeadings(data.page.headings) }),
393
403
  children ?? /* @__PURE__ */ jsx3("div", { className: "documentation-prose", dangerouslySetInnerHTML: { __html: data.page.html } }),
404
+ codeBlocks.map((mount) => createPortal(
405
+ /* @__PURE__ */ jsx3(
406
+ CodeBlockActions,
407
+ {
408
+ assistantEnabled: data.config.assistant.access !== "disabled",
409
+ onAsk: (code) => onAssistantOpen(`Explain this ${data.page.title} example and the important details:
410
+
411
+ ${code}`),
412
+ pre: mount.pre
413
+ }
414
+ ),
415
+ mount.host,
416
+ mount.key
417
+ )),
394
418
  data.page.openapi?.playground && /* @__PURE__ */ jsx3(ApiPlayground, { operation: data.page.openapi }),
419
+ launcher,
395
420
  /* @__PURE__ */ jsxs3("nav", { className: "documentation-pagination", "aria-label": "Page navigation", children: [
396
421
  data.previous ? /* @__PURE__ */ jsxs3("a", { rel: "prev", href: documentationPublicPath(data.basePath, data.previous.route), children: [
397
422
  /* @__PURE__ */ jsx3("small", { children: "Previous" }),
@@ -416,13 +441,38 @@ function Breadcrumbs({ items }) {
416
441
  item
417
442
  ] }, `${item}:${items.slice(0, index + 1).join("/")}`)) });
418
443
  }
444
+ function outlineHeadings(headings) {
445
+ return headings.filter((heading) => heading.depth === 2 || heading.depth === 3);
446
+ }
447
+ function OutlineLinks({
448
+ active,
449
+ headings
450
+ }) {
451
+ return /* @__PURE__ */ jsx3(Fragment2, { children: headings.map((heading) => /* @__PURE__ */ jsx3(
452
+ "a",
453
+ {
454
+ "aria-current": active === heading.id ? "location" : void 0,
455
+ className: `${heading.depth === 3 ? "depth-3 " : ""}${active === heading.id ? "is-active" : ""}`,
456
+ href: `#${heading.id}`,
457
+ children: heading.text
458
+ },
459
+ heading.id
460
+ )) });
461
+ }
462
+ function OutlineDisclosure({ headings }) {
463
+ if (headings.length === 0) return null;
464
+ return /* @__PURE__ */ jsxs3("details", { className: "documentation-outline-disclosure", children: [
465
+ /* @__PURE__ */ jsxs3("summary", { children: [
466
+ /* @__PURE__ */ jsx3(ListIcon, {}),
467
+ "On this page"
468
+ ] }),
469
+ /* @__PURE__ */ jsx3("nav", { className: "documentation-outline", "aria-label": "On this page", children: /* @__PURE__ */ jsx3(OutlineLinks, { active: "", headings }) })
470
+ ] });
471
+ }
419
472
  function ContextRail({
420
473
  data
421
474
  }) {
422
- const headings = useMemo(
423
- () => data.page.headings.filter((heading) => heading.depth === 2 || heading.depth === 3),
424
- [data.page.headings]
425
- );
475
+ const headings = useMemo(() => outlineHeadings(data.page.headings), [data.page.headings]);
426
476
  const [active, setActive] = useState2(headings[0]?.id ?? "");
427
477
  useEffect2(() => setActive(headings[0]?.id ?? ""), [headings]);
428
478
  useEffect2(() => {
@@ -437,16 +487,7 @@ function ContextRail({
437
487
  }, [headings]);
438
488
  return /* @__PURE__ */ jsx3("aside", { className: "documentation-context-rail", "aria-label": "Page context", children: headings.length > 0 && /* @__PURE__ */ jsxs3("nav", { className: "documentation-outline", "aria-label": "On this page", children: [
439
489
  /* @__PURE__ */ jsx3("h2", { children: "On this page" }),
440
- headings.map((heading) => /* @__PURE__ */ jsx3(
441
- "a",
442
- {
443
- "aria-current": active === heading.id ? "location" : void 0,
444
- className: `${heading.depth === 3 ? "depth-3 " : ""}${active === heading.id ? "is-active" : ""}`,
445
- href: `#${heading.id}`,
446
- children: heading.text
447
- },
448
- heading.id
449
- ))
490
+ /* @__PURE__ */ jsx3(OutlineLinks, { active, headings })
450
491
  ] }) });
451
492
  }
452
493
  function ApiPlayground({ operation }) {
@@ -499,49 +540,74 @@ ${text}`);
499
540
  /* @__PURE__ */ jsx3("pre", { "aria-live": "polite", children: responseText })
500
541
  ] });
501
542
  }
502
- function useArticleEnhancements(articleRef, data, onAssistantOpen) {
543
+ function useCodeBlockMounts(articleRef, route) {
544
+ const [mounts, setMounts] = useState2([]);
503
545
  useEffect2(() => {
504
546
  const article = articleRef.current;
505
547
  if (!article) return;
506
- const cleanups = [];
507
- article.querySelectorAll(".documentation-prose pre").forEach((pre) => {
508
- if (pre.querySelector(".documentation-code-actions")) return;
509
- const controls = document.createElement("div");
510
- controls.className = "documentation-code-actions";
511
- const copy = document.createElement("button");
512
- copy.type = "button";
513
- copy.setAttribute("aria-label", "Copy code");
514
- copy.textContent = "Copy";
515
- const copyHandler = async () => {
516
- await writeClipboardText(pre.querySelector("code")?.textContent ?? pre.textContent ?? "");
517
- copy.textContent = "Copied";
518
- window.setTimeout(() => {
519
- copy.textContent = "Copy";
520
- }, 1400);
521
- };
522
- copy.addEventListener("click", copyHandler);
523
- controls.appendChild(copy);
524
- if (data.config.assistant.access !== "disabled") {
525
- const ask = document.createElement("button");
526
- ask.type = "button";
527
- ask.textContent = "Ask";
528
- ask.setAttribute("aria-label", "Ask the documentation assistant about this code");
529
- const askHandler = () => {
530
- const code = pre.querySelector("code")?.textContent?.trim().slice(0, 1200) ?? "";
531
- onAssistantOpen(`Explain this ${data.page.title} example and the important details:
532
-
533
- ${code}`);
534
- };
535
- ask.addEventListener("click", askHandler);
536
- controls.appendChild(ask);
537
- cleanups.push(() => ask.removeEventListener("click", askHandler));
548
+ const created = [];
549
+ const next = [];
550
+ article.querySelectorAll(".documentation-prose pre").forEach((pre, index) => {
551
+ const block = document.createElement("div");
552
+ block.className = "documentation-code-block";
553
+ pre.replaceWith(block);
554
+ block.appendChild(pre);
555
+ const language = codeBlockLanguage(pre);
556
+ if (language) {
557
+ const label = document.createElement("span");
558
+ label.className = "documentation-code-language";
559
+ label.textContent = language;
560
+ block.appendChild(label);
538
561
  }
539
- pre.appendChild(controls);
540
- cleanups.push(() => {
541
- copy.removeEventListener("click", copyHandler);
542
- controls.remove();
543
- });
562
+ const host = document.createElement("div");
563
+ host.className = "documentation-code-actions";
564
+ block.appendChild(host);
565
+ created.push({ block, pre });
566
+ next.push({ key: `${route}:${index}`, host, pre });
544
567
  });
568
+ setMounts(next);
569
+ return () => {
570
+ setMounts([]);
571
+ for (const { block, pre } of created) block.replaceWith(pre);
572
+ };
573
+ }, [articleRef, route]);
574
+ return mounts;
575
+ }
576
+ function codeBlockLanguage(pre) {
577
+ const className = pre.querySelector("code")?.className ?? "";
578
+ return /(?:^|\s)(?:language|lang)-([a-z0-9+#-]{1,20})/i.exec(className)?.[1] ?? "";
579
+ }
580
+ function CodeBlockActions({
581
+ assistantEnabled,
582
+ onAsk,
583
+ pre
584
+ }) {
585
+ const [copied, setCopied] = useState2(false);
586
+ const copy = async () => {
587
+ await writeClipboardText(pre.querySelector("code")?.textContent ?? pre.textContent ?? "");
588
+ setCopied(true);
589
+ window.setTimeout(() => setCopied(false), 1400);
590
+ };
591
+ return /* @__PURE__ */ jsxs3(Fragment2, { children: [
592
+ /* @__PURE__ */ jsx3("button", { "aria-label": copied ? "Code copied" : "Copy code", onClick: () => {
593
+ void copy();
594
+ }, type: "button", children: copied ? /* @__PURE__ */ jsx3(CheckIcon, {}) : /* @__PURE__ */ jsx3(CopyIcon, {}) }),
595
+ assistantEnabled && /* @__PURE__ */ jsx3(
596
+ "button",
597
+ {
598
+ "aria-label": "Ask the documentation assistant about this code",
599
+ onClick: () => onAsk(pre.querySelector("code")?.textContent?.trim().slice(0, 1200) ?? ""),
600
+ type: "button",
601
+ children: /* @__PURE__ */ jsx3(SparkIcon, {})
602
+ }
603
+ )
604
+ ] });
605
+ }
606
+ function useArticleEnhancements(articleRef, data, onAssistantOpen) {
607
+ useEffect2(() => {
608
+ const article = articleRef.current;
609
+ if (!article) return;
610
+ const cleanups = [];
545
611
  article.querySelectorAll("[data-tab-group]").forEach((group, groupIndex) => {
546
612
  if (group.querySelector(":scope > .documentation-tab-buttons")) return;
547
613
  const tabs = Array.from(group.querySelectorAll(":scope > [data-tab]"));
@@ -714,8 +780,7 @@ function AssistantLauncher({
714
780
  name,
715
781
  onInputChange,
716
782
  onOpen,
717
- onSubmit,
718
- open
783
+ onSubmit
719
784
  }) {
720
785
  const subject = documentationSubject(name);
721
786
  const submit = (event) => {
@@ -724,7 +789,6 @@ function AssistantLauncher({
724
789
  if (!question) return;
725
790
  onSubmit(question);
726
791
  };
727
- if (open) return null;
728
792
  return /* @__PURE__ */ jsxs4(
729
793
  "form",
730
794
  {
@@ -734,7 +798,7 @@ function AssistantLauncher({
734
798
  children: [
735
799
  /* @__PURE__ */ jsxs4("button", { className: "documentation-launcher-agent", type: "button", onClick: onOpen, "aria-label": `Open the ${subject} agent`, children: [
736
800
  "Ask ",
737
- name
801
+ /* @__PURE__ */ jsx4("span", { className: "documentation-launcher-agent-name", children: name })
738
802
  ] }),
739
803
  /* @__PURE__ */ jsx4(
740
804
  "input",
@@ -747,6 +811,10 @@ function AssistantLauncher({
747
811
  value: input
748
812
  }
749
813
  ),
814
+ /* @__PURE__ */ jsxs4("span", { "aria-hidden": "true", className: "documentation-launcher-hint", children: [
815
+ /* @__PURE__ */ jsx4("kbd", { children: "\u2318" }),
816
+ /* @__PURE__ */ jsx4("kbd", { children: "I" })
817
+ ] }),
750
818
  /* @__PURE__ */ jsx4("button", { className: "documentation-launcher-send", type: "submit", disabled: !input.trim(), "aria-label": "Send question to documentation agent", children: /* @__PURE__ */ jsx4(SendIcon, {}) })
751
819
  ]
752
820
  }
@@ -1024,7 +1092,7 @@ function renderInlineMarkdown(value) {
1024
1092
 
1025
1093
  // src/documentation/runtime/navigation.tsx
1026
1094
  import { useEffect as useEffect5, useRef as useRef4, useState as useState4 } from "react";
1027
- import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1095
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1028
1096
  function DocumentationHeader({
1029
1097
  data,
1030
1098
  onMenuOpen,
@@ -1059,13 +1127,13 @@ function DocumentationHeader({
1059
1127
  function BrandLogo({ data }) {
1060
1128
  const { logo, logoDark } = data.config.theme;
1061
1129
  if (logo) {
1062
- return /* @__PURE__ */ jsxs5(Fragment2, { children: [
1130
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
1063
1131
  /* @__PURE__ */ jsx5("img", { className: "documentation-brand-logo documentation-brand-logo-light", src: logo, alt: "" }),
1064
1132
  /* @__PURE__ */ jsx5("img", { className: "documentation-brand-logo documentation-brand-logo-dark", src: logoDark ?? logo, alt: "" }),
1065
1133
  /* @__PURE__ */ jsx5("span", { className: "documentation-brand-product", children: "Documentation" })
1066
1134
  ] });
1067
1135
  }
1068
- return /* @__PURE__ */ jsxs5(Fragment2, { children: [
1136
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
1069
1137
  /* @__PURE__ */ jsx5("span", { className: "documentation-brand-mark", children: /* @__PURE__ */ jsx5(OrbitMark, {}) }),
1070
1138
  /* @__PURE__ */ jsx5("span", { className: "documentation-brand-name", children: data.config.name })
1071
1139
  ] });
@@ -1086,7 +1154,7 @@ function NavigationTree({
1086
1154
  depth = 0,
1087
1155
  nodes
1088
1156
  }) {
1089
- return /* @__PURE__ */ jsx5(Fragment2, { children: nodes.map((node) => {
1157
+ return /* @__PURE__ */ jsx5(Fragment3, { children: nodes.map((node) => {
1090
1158
  if (node.kind === "group") {
1091
1159
  const active2 = containsRoute(node, activeRoute);
1092
1160
  if (depth === 0) {
@@ -1190,7 +1258,7 @@ import {
1190
1258
  useRef as useRef5,
1191
1259
  useState as useState5
1192
1260
  } from "react";
1193
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1261
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1194
1262
  function SearchCommand({
1195
1263
  assistantEnabled,
1196
1264
  basePath,
@@ -1201,6 +1269,7 @@ function SearchCommand({
1201
1269
  open
1202
1270
  }) {
1203
1271
  const dialogRef = useRef5(null);
1272
+ const resultsRef = useRef5(null);
1204
1273
  const [index, setIndex] = useState5(null);
1205
1274
  const [loading, setLoading] = useState5(false);
1206
1275
  const [query, setQuery] = useState5("");
@@ -1217,6 +1286,9 @@ function SearchCommand({
1217
1286
  setActiveIndex(0);
1218
1287
  }
1219
1288
  }, [open]);
1289
+ useEffect6(() => {
1290
+ resultsRef.current?.querySelector(`#documentation-search-option-${activeIndex}`)?.scrollIntoView({ block: "nearest" });
1291
+ }, [activeIndex, query]);
1220
1292
  const preparedIndex = useMemo2(() => prepareSearchIndex(index ?? []), [index]);
1221
1293
  const results = useMemo2(() => rankSearch(preparedIndex, query), [preparedIndex, query]);
1222
1294
  if (!open) return null;
@@ -1230,9 +1302,10 @@ function SearchCommand({
1230
1302
  setActiveIndex((current) => (current - 1 + selectableCount) % selectableCount);
1231
1303
  } else if (event.key === "Enter") {
1232
1304
  event.preventDefault();
1233
- if (activeIndex < results.length && results[activeIndex]) {
1305
+ const result = activeIndex < results.length ? results[activeIndex] : void 0;
1306
+ if (result) {
1234
1307
  onClose();
1235
- const href = documentationPublicPath(basePath, results[activeIndex].route);
1308
+ const href = documentationPublicPath(basePath, result.href);
1236
1309
  if (onNavigate) onNavigate(href);
1237
1310
  else window.location.assign(href);
1238
1311
  } else if (assistantEnabled && query.trim()) {
@@ -1266,7 +1339,7 @@ function SearchCommand({
1266
1339
  ),
1267
1340
  /* @__PURE__ */ jsx6("kbd", { children: "Esc" })
1268
1341
  ] }),
1269
- /* @__PURE__ */ jsxs6("div", { className: "documentation-search-results", id: "documentation-search-results", role: "listbox", "aria-label": "Search results", children: [
1342
+ /* @__PURE__ */ jsxs6("div", { className: "documentation-search-results", id: "documentation-search-results", ref: resultsRef, role: "listbox", "aria-label": "Search results", children: [
1270
1343
  !query.trim() && /* @__PURE__ */ jsxs6("div", { className: "documentation-search-empty", children: [
1271
1344
  /* @__PURE__ */ jsx6(OrbitMark, {}),
1272
1345
  /* @__PURE__ */ jsx6("strong", { children: "Find an answer in this commit" }),
@@ -1283,20 +1356,25 @@ function SearchCommand({
1283
1356
  {
1284
1357
  "aria-selected": activeIndex === resultIndex,
1285
1358
  className: activeIndex === resultIndex ? "documentation-search-result is-active" : "documentation-search-result",
1286
- href: documentationPublicPath(basePath, result.route),
1359
+ href: documentationPublicPath(basePath, result.href),
1287
1360
  id: `documentation-search-option-${resultIndex}`,
1288
1361
  onClick: onClose,
1289
1362
  onMouseEnter: () => setActiveIndex(resultIndex),
1290
1363
  role: "option",
1291
1364
  children: [
1292
- /* @__PURE__ */ jsxs6("span", { children: [
1365
+ /* @__PURE__ */ jsx6("span", { className: "documentation-search-kind", children: result.kind === "section" ? /* @__PURE__ */ jsx6(HashIcon, {}) : /* @__PURE__ */ jsx6(FileIcon, {}) }),
1366
+ /* @__PURE__ */ jsxs6("span", { className: "documentation-search-copy", children: [
1293
1367
  /* @__PURE__ */ jsx6("strong", { children: highlightMatch(result.title, query) }),
1294
- /* @__PURE__ */ jsx6("small", { children: result.description ?? result.headings[0] ?? result.text.slice(0, 150) })
1368
+ result.kind === "section" ? /* @__PURE__ */ jsxs6("span", { className: "documentation-search-crumbs", children: [
1369
+ result.context,
1370
+ /* @__PURE__ */ jsx6(ChevronRightIcon, {}),
1371
+ result.title
1372
+ ] }) : /* @__PURE__ */ jsx6("small", { children: result.context })
1295
1373
  ] }),
1296
1374
  /* @__PURE__ */ jsx6(ChevronRightIcon, {})
1297
1375
  ]
1298
1376
  },
1299
- result.route
1377
+ result.href
1300
1378
  )),
1301
1379
  assistantEnabled && query.trim() && /* @__PURE__ */ jsxs6(
1302
1380
  "button",
@@ -1340,7 +1418,8 @@ function prepareSearchIndex(index) {
1340
1418
  return index.map((entry) => ({
1341
1419
  entry,
1342
1420
  title: normalizeSearch(entry.title),
1343
- headings: normalizeSearch(entry.headings.join(" ")),
1421
+ headings: entry.headings.map((heading) => ({ heading, normalized: normalizeSearch(heading.text) })),
1422
+ headingText: normalizeSearch(entry.headings.map((heading) => heading.text).join(" ")),
1344
1423
  haystack: normalizeSearch(`${entry.description ?? ""} ${entry.text}`)
1345
1424
  }));
1346
1425
  }
@@ -1348,24 +1427,54 @@ function rankSearch(index, query) {
1348
1427
  const normalized = normalizeSearch(query);
1349
1428
  if (!normalized) return [];
1350
1429
  const tokens = normalized.split(" ").filter(Boolean);
1351
- return index.map(({ entry, title, headings, haystack }) => {
1430
+ const scored = [];
1431
+ for (const { entry, title, headings, headingText, haystack } of index) {
1352
1432
  let score = title === normalized ? 180 : title.startsWith(normalized) ? 110 : title.includes(normalized) ? 75 : 0;
1353
- if (headings.includes(normalized)) score += 55;
1433
+ if (headingText.includes(normalized)) score += 55;
1354
1434
  for (const token of tokens) {
1355
1435
  if (title.includes(token)) score += 24;
1356
- else if (headings.includes(token)) score += 14;
1436
+ else if (headingText.includes(token)) score += 14;
1357
1437
  else if (haystack.includes(token)) score += 5;
1358
1438
  else score -= 18;
1359
1439
  }
1360
- return { entry, score };
1361
- }).filter((item) => item.score > 0).sort((left, right) => right.score - left.score || left.entry.route.localeCompare(right.entry.route)).slice(0, 10).map((item) => item.entry);
1440
+ if (score > 0) {
1441
+ scored.push({
1442
+ route: entry.route,
1443
+ score,
1444
+ result: {
1445
+ href: entry.route,
1446
+ kind: "page",
1447
+ title: entry.title,
1448
+ context: entry.description ?? entry.text.slice(0, 150)
1449
+ }
1450
+ });
1451
+ }
1452
+ for (const { heading, normalized: headingNormalized } of headings) {
1453
+ let sectionScore = headingNormalized === normalized ? 120 : headingNormalized.startsWith(normalized) ? 80 : headingNormalized.includes(normalized) ? 60 : 0;
1454
+ if (sectionScore === 0) {
1455
+ for (const token of tokens) if (headingNormalized.includes(token)) sectionScore += 18;
1456
+ }
1457
+ if (sectionScore <= 0) continue;
1458
+ scored.push({
1459
+ route: `${entry.route}#${heading.id}`,
1460
+ score: sectionScore,
1461
+ result: {
1462
+ href: `${entry.route}#${heading.id}`,
1463
+ kind: "section",
1464
+ title: heading.text,
1465
+ context: entry.title
1466
+ }
1467
+ });
1468
+ }
1469
+ }
1470
+ return scored.sort((left, right) => right.score - left.score || left.route.localeCompare(right.route)).slice(0, 10).map((item) => item.result);
1362
1471
  }
1363
1472
  function highlightMatch(value, query) {
1364
1473
  const normalizedQuery = query.trim();
1365
1474
  if (!normalizedQuery) return value;
1366
1475
  const index = value.toLowerCase().indexOf(normalizedQuery.toLowerCase());
1367
1476
  if (index < 0) return value;
1368
- return /* @__PURE__ */ jsxs6(Fragment3, { children: [
1477
+ return /* @__PURE__ */ jsxs6(Fragment4, { children: [
1369
1478
  value.slice(0, index),
1370
1479
  /* @__PURE__ */ jsx6("mark", { children: value.slice(index, index + normalizedQuery.length) }),
1371
1480
  value.slice(index + normalizedQuery.length)
@@ -1376,7 +1485,7 @@ function normalizeSearch(value) {
1376
1485
  }
1377
1486
 
1378
1487
  // src/documentation/runtime/app.tsx
1379
- import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1488
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1380
1489
  function DocumentationApp({
1381
1490
  data,
1382
1491
  children,
@@ -1438,7 +1547,24 @@ function DocumentationApp({
1438
1547
  /* @__PURE__ */ jsxs7("div", { className: "documentation-frame", children: [
1439
1548
  /* @__PURE__ */ jsx7(DesktopSidebar, { data }),
1440
1549
  /* @__PURE__ */ jsx7("main", { className: "documentation-main", id: "documentation-content", children: /* @__PURE__ */ jsxs7("div", { className: "documentation-reader-grid", children: [
1441
- /* @__PURE__ */ jsx7(Article, { data, onAssistantOpen: openAssistant, children }),
1550
+ /* @__PURE__ */ jsx7("div", { className: "documentation-reader-column", children: /* @__PURE__ */ jsx7(
1551
+ Article,
1552
+ {
1553
+ data,
1554
+ launcher: assistantAccess && !assistantOpen ? /* @__PURE__ */ jsx7("div", { className: "documentation-launcher-dock", children: /* @__PURE__ */ jsx7(
1555
+ AssistantLauncher,
1556
+ {
1557
+ input: assistantDraft,
1558
+ name: data.config.name,
1559
+ onOpen: () => openAssistant(),
1560
+ onInputChange: setAssistantDraft,
1561
+ onSubmit: (question) => openAssistant(question, true)
1562
+ }
1563
+ ) }) : void 0,
1564
+ onAssistantOpen: openAssistant,
1565
+ children
1566
+ }
1567
+ ) }),
1442
1568
  /* @__PURE__ */ jsx7(ContextRail, { data })
1443
1569
  ] }) })
1444
1570
  ] }),
@@ -1462,34 +1588,21 @@ function DocumentationApp({
1462
1588
  open: searchOpen
1463
1589
  }
1464
1590
  ),
1465
- assistantAccess && /* @__PURE__ */ jsxs7(Fragment4, { children: [
1466
- /* @__PURE__ */ jsx7(
1467
- AssistantLauncher,
1468
- {
1469
- input: assistantDraft,
1470
- name: data.config.name,
1471
- onOpen: () => openAssistant(),
1472
- onInputChange: setAssistantDraft,
1473
- onSubmit: (question) => openAssistant(question, true),
1474
- open: assistantOpen
1475
- }
1476
- ),
1477
- /* @__PURE__ */ jsx7(
1478
- DocumentationAssistant,
1479
- {
1480
- access: assistantAccess,
1481
- basePath: data.basePath,
1482
- input: assistantDraft,
1483
- name: data.config.name,
1484
- onClose: () => setAssistantOpen(false),
1485
- onInputChange: setAssistantDraft,
1486
- open: assistantOpen,
1487
- route: data.page.route,
1488
- seed: assistantSeed,
1489
- suggestions: data.config.assistant.suggestions
1490
- }
1491
- )
1492
- ] })
1591
+ assistantAccess && /* @__PURE__ */ jsx7(
1592
+ DocumentationAssistant,
1593
+ {
1594
+ access: assistantAccess,
1595
+ basePath: data.basePath,
1596
+ input: assistantDraft,
1597
+ name: data.config.name,
1598
+ onClose: () => setAssistantOpen(false),
1599
+ onInputChange: setAssistantDraft,
1600
+ open: assistantOpen,
1601
+ route: data.page.route,
1602
+ seed: assistantSeed,
1603
+ suggestions: data.config.assistant.suggestions
1604
+ }
1605
+ )
1493
1606
  ]
1494
1607
  }
1495
1608
  );
@@ -1635,4 +1748,4 @@ export {
1635
1748
  DefaultDocumentation,
1636
1749
  DocumentationContent
1637
1750
  };
1638
- //# sourceMappingURL=chunk-T7V4GUIN.js.map
1751
+ //# sourceMappingURL=chunk-ZJ43EK3N.js.map