@clarify-labs/renderer 0.7.1 → 0.8.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.
Files changed (60) hide show
  1. package/output/{ThemeRoot-CLa0yvRQ.js → ClarifyShell-BxB_6Uhd.js} +292 -141
  2. package/output/ClarifyShell-BxB_6Uhd.js.map +1 -0
  3. package/output/{ThemeRoot-DYS-lcK-.cjs → ClarifyShell-DNN5erFD.cjs} +320 -145
  4. package/output/ClarifyShell-DNN5erFD.cjs.map +1 -0
  5. package/output/{OpenApiOperation-C4xZu4i0.cjs → OpenApiOperation-9SvCA_B4.cjs} +327 -83
  6. package/output/OpenApiOperation-9SvCA_B4.cjs.map +1 -0
  7. package/output/{OpenApiOperation-LIL7bqxW.js → OpenApiOperation-J41rHO2l.js} +323 -85
  8. package/output/OpenApiOperation-J41rHO2l.js.map +1 -0
  9. package/output/{PageActions-yoDRjkq8.js → PageActions-DR0asnKH.js} +30 -69
  10. package/output/PageActions-DR0asnKH.js.map +1 -0
  11. package/output/{PageActions-1RDCHcUY.cjs → PageActions-yycPlNyL.cjs} +35 -68
  12. package/output/PageActions-yycPlNyL.cjs.map +1 -0
  13. package/output/app/AppShell.d.ts +2 -3
  14. package/output/app/PageBanner.d.ts +0 -2
  15. package/output/app/PageFooter.d.ts +1 -5
  16. package/output/client.cjs +8 -8
  17. package/output/client.js +3 -3
  18. package/output/components/Code.d.ts +5 -1
  19. package/output/components/Mermaid.d.ts +7 -0
  20. package/output/components/index.d.ts +1 -0
  21. package/output/context.d.ts +1 -1
  22. package/output/core/i18n.d.ts +1 -1
  23. package/output/core/types.d.ts +7 -14
  24. package/output/index.cjs +27 -24
  25. package/output/index.cjs.map +1 -1
  26. package/output/index.d.ts +7 -4
  27. package/output/index.js +14 -14
  28. package/output/index.js.map +1 -1
  29. package/output/mdx/components.d.ts +4 -0
  30. package/output/mdx/primitives.d.ts +2 -0
  31. package/output/openapi/components/EndpointSections.d.ts +30 -0
  32. package/output/preview.cjs +2 -2
  33. package/output/preview.cjs.map +1 -1
  34. package/output/preview.js +2 -2
  35. package/output/preview.js.map +1 -1
  36. package/output/{render-CRTqZzyY.cjs → render-CWvm77UW.cjs} +10 -20
  37. package/output/render-CWvm77UW.cjs.map +1 -0
  38. package/output/{render-D0ls3d2j.js → render-mGozubG5.js} +10 -20
  39. package/output/render-mGozubG5.js.map +1 -0
  40. package/output/renderer.css +83 -24
  41. package/output/runtime/ClarifyShell.d.ts +22 -0
  42. package/output/server.cjs +10 -19
  43. package/output/server.cjs.map +1 -1
  44. package/output/server.js +10 -19
  45. package/output/server.js.map +1 -1
  46. package/output/shell/search/pagefind.d.ts +0 -1
  47. package/output/slots/RuntimeSlot.d.ts +58 -0
  48. package/output/slots/context.d.ts +20 -0
  49. package/output/slots/index.d.ts +5 -0
  50. package/output/slots/types.d.ts +50 -0
  51. package/output/utils/localized-text.d.ts +7 -0
  52. package/package.json +8 -3
  53. package/output/OpenApiOperation-C4xZu4i0.cjs.map +0 -1
  54. package/output/OpenApiOperation-LIL7bqxW.js.map +0 -1
  55. package/output/PageActions-1RDCHcUY.cjs.map +0 -1
  56. package/output/PageActions-yoDRjkq8.js.map +0 -1
  57. package/output/ThemeRoot-CLa0yvRQ.js.map +0 -1
  58. package/output/ThemeRoot-DYS-lcK-.cjs.map +0 -1
  59. package/output/render-CRTqZzyY.cjs.map +0 -1
  60. package/output/render-D0ls3d2j.js.map +0 -1
@@ -1278,6 +1278,10 @@
1278
1278
  flex: none;
1279
1279
  margin-top: .45rem;
1280
1280
  }
1281
+
1282
+ .prose thead th, .prose :not(pre) > code {
1283
+ white-space: nowrap;
1284
+ }
1281
1285
  }
1282
1286
 
1283
1287
  @layer utilities {
@@ -1353,6 +1357,10 @@
1353
1357
  top: 50%;
1354
1358
  }
1355
1359
 
1360
+ .top-2 {
1361
+ top: calc(var(--spacing) * 2);
1362
+ }
1363
+
1356
1364
  .top-3\.5 {
1357
1365
  top: calc(var(--spacing) * 3.5);
1358
1366
  }
@@ -1369,6 +1377,10 @@
1369
1377
  right: 0;
1370
1378
  }
1371
1379
 
1380
+ .right-2 {
1381
+ right: calc(var(--spacing) * 2);
1382
+ }
1383
+
1372
1384
  .right-3 {
1373
1385
  right: calc(var(--spacing) * 3);
1374
1386
  }
@@ -1381,6 +1393,10 @@
1381
1393
  bottom: 0;
1382
1394
  }
1383
1395
 
1396
+ .bottom-2 {
1397
+ bottom: calc(var(--spacing) * 2);
1398
+ }
1399
+
1384
1400
  .bottom-4 {
1385
1401
  bottom: calc(var(--spacing) * 4);
1386
1402
  }
@@ -1732,7 +1748,6 @@
1732
1748
  .prose :where(table):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
1733
1749
  table-layout: auto;
1734
1750
  text-align: left;
1735
- width: 100%;
1736
1751
  margin-top: 2rem;
1737
1752
  margin-bottom: 2rem;
1738
1753
  line-height: 1.5rem;
@@ -1798,6 +1813,10 @@
1798
1813
  color: inherit;
1799
1814
  }
1800
1815
 
1816
+ .prose :where(:is(tbody, tfoot) td code):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
1817
+ white-space: normal;
1818
+ }
1819
+
1801
1820
  .prose :where(:is(h1, h2, h3) + *):not(:where([class~="not-prose"], [class~="not-prose"] *)) {
1802
1821
  margin-top: 0;
1803
1822
  }
@@ -2126,6 +2145,10 @@
2126
2145
  min-height: 100vh;
2127
2146
  }
2128
2147
 
2148
+ .\!w-full {
2149
+ width: 100% !important;
2150
+ }
2151
+
2129
2152
  .w-\(--clarify-schema-row-nested-width\) {
2130
2153
  width: var(--clarify-schema-row-nested-width);
2131
2154
  }
@@ -2190,6 +2213,10 @@
2190
2213
  width: calc(var(--spacing) * 6);
2191
2214
  }
2192
2215
 
2216
+ .w-7 {
2217
+ width: calc(var(--spacing) * 7);
2218
+ }
2219
+
2193
2220
  .w-8 {
2194
2221
  width: calc(var(--spacing) * 8);
2195
2222
  }
@@ -2346,6 +2373,10 @@
2346
2373
  flex-shrink: 0;
2347
2374
  }
2348
2375
 
2376
+ .grow {
2377
+ flex-grow: 1;
2378
+ }
2379
+
2349
2380
  .origin-top {
2350
2381
  transform-origin: top;
2351
2382
  }
@@ -2399,6 +2430,10 @@
2399
2430
  animation: var(--animate-spin);
2400
2431
  }
2401
2432
 
2433
+ .\!cursor-grab {
2434
+ cursor: grab !important;
2435
+ }
2436
+
2402
2437
  .cursor-default {
2403
2438
  cursor: default;
2404
2439
  }
@@ -2537,12 +2572,6 @@
2537
2572
  margin-block-end: calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)));
2538
2573
  }
2539
2574
 
2540
- :where(.space-y-6 > :not(:last-child)) {
2541
- --tw-space-y-reverse: 0;
2542
- margin-block-start: calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));
2543
- margin-block-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)));
2544
- }
2545
-
2546
2575
  :where(.space-y-8 > :not(:last-child)) {
2547
2576
  --tw-space-y-reverse: 0;
2548
2577
  margin-block-start: calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));
@@ -2605,10 +2634,6 @@
2605
2634
  }
2606
2635
  }
2607
2636
 
2608
- .self-end {
2609
- align-self: flex-end;
2610
- }
2611
-
2612
2637
  .truncate {
2613
2638
  text-overflow: ellipsis;
2614
2639
  white-space: nowrap;
@@ -2879,7 +2904,17 @@
2879
2904
  background-color: var(--clarify-theme-tokens-colors-primary);
2880
2905
  }
2881
2906
 
2882
- .bg-\(--clarify-theme-tokens-colors-surface\), .bg-\(--clarify-theme-tokens-colors-surface\)\/95 {
2907
+ .bg-\(--clarify-theme-tokens-colors-surface\), .bg-\(--clarify-theme-tokens-colors-surface\)\/90 {
2908
+ background-color: var(--clarify-theme-tokens-colors-surface);
2909
+ }
2910
+
2911
+ @supports (color: color-mix(in lab, red, red)) {
2912
+ .bg-\(--clarify-theme-tokens-colors-surface\)\/90 {
2913
+ background-color: color-mix(in oklab, var(--clarify-theme-tokens-colors-surface) 90%, transparent);
2914
+ }
2915
+ }
2916
+
2917
+ .bg-\(--clarify-theme-tokens-colors-surface\)\/95 {
2883
2918
  background-color: var(--clarify-theme-tokens-colors-surface);
2884
2919
  }
2885
2920
 
@@ -3295,8 +3330,8 @@
3295
3330
  padding-top: calc(var(--spacing) * 16);
3296
3331
  }
3297
3332
 
3298
- .pt-\[6\.5rem\] {
3299
- padding-top: 6.5rem;
3333
+ .pt-26 {
3334
+ padding-top: calc(var(--spacing) * 26);
3300
3335
  }
3301
3336
 
3302
3337
  .pr-3 {
@@ -3335,6 +3370,10 @@
3335
3370
  padding-bottom: calc(var(--spacing) * 12);
3336
3371
  }
3337
3372
 
3373
+ .pb-16 {
3374
+ padding-bottom: calc(var(--spacing) * 16);
3375
+ }
3376
+
3338
3377
  .pl-1\.5 {
3339
3378
  padding-left: calc(var(--spacing) * 1.5);
3340
3379
  }
@@ -3504,14 +3543,14 @@
3504
3543
  letter-spacing: var(--tracking-widest);
3505
3544
  }
3506
3545
 
3507
- .break-words {
3508
- overflow-wrap: break-word;
3509
- }
3510
-
3511
3546
  .wrap-anywhere {
3512
3547
  overflow-wrap: anywhere;
3513
3548
  }
3514
3549
 
3550
+ .wrap-break-word {
3551
+ overflow-wrap: break-word;
3552
+ }
3553
+
3515
3554
  .whitespace-normal {
3516
3555
  white-space: normal;
3517
3556
  }
@@ -4077,6 +4116,10 @@
4077
4116
  display: none;
4078
4117
  }
4079
4118
 
4119
+ .focus-within\:opacity-100:focus-within {
4120
+ opacity: 1;
4121
+ }
4122
+
4080
4123
  @media (hover: hover) {
4081
4124
  .hover\:scale-105:hover {
4082
4125
  --tw-scale-x: 105%;
@@ -4208,6 +4251,10 @@
4208
4251
  outline-style: none;
4209
4252
  }
4210
4253
 
4254
+ .active\:\!cursor-grabbing:active {
4255
+ cursor: grabbing !important;
4256
+ }
4257
+
4211
4258
  .data-closed\:-translate-x-full[data-closed] {
4212
4259
  --tw-translate-x: -100%;
4213
4260
  translate: var(--tw-translate-x) var(--tw-translate-y);
@@ -4480,6 +4527,10 @@
4480
4527
  top: calc(var(--spacing) * 14);
4481
4528
  }
4482
4529
 
4530
+ .lg\:top-26 {
4531
+ top: calc(var(--spacing) * 26);
4532
+ }
4533
+
4483
4534
  .lg\:top-28 {
4484
4535
  top: calc(var(--spacing) * 28);
4485
4536
  }
@@ -4488,10 +4539,6 @@
4488
4539
  top: calc(var(--spacing) * 40);
4489
4540
  }
4490
4541
 
4491
- .lg\:top-\[6\.5rem\] {
4492
- top: 6.5rem;
4493
- }
4494
-
4495
4542
  .lg\:z-30 {
4496
4543
  z-index: 30;
4497
4544
  }
@@ -4594,8 +4641,8 @@
4594
4641
  position: sticky;
4595
4642
  }
4596
4643
 
4597
- .xl\:top-24 {
4598
- top: calc(var(--spacing) * 24);
4644
+ .xl\:top-\[calc\(var\(--clarify-header-offset\,3\.5rem\)\+1\.5rem\)\] {
4645
+ top: calc(var(--clarify-header-offset, 3.5rem) + 1.5rem);
4599
4646
  }
4600
4647
 
4601
4648
  .xl\:max-w-none {
@@ -4614,6 +4661,10 @@
4614
4661
  grid-template-columns: repeat(4, minmax(0, 1fr));
4615
4662
  }
4616
4663
 
4664
+ .xl\:self-start {
4665
+ align-self: flex-start;
4666
+ }
4667
+
4617
4668
  .xl\:px-6 {
4618
4669
  padding-inline: calc(var(--spacing) * 6);
4619
4670
  }
@@ -5223,6 +5274,14 @@
5223
5274
  }
5224
5275
  }
5225
5276
 
5277
+ .\[\&_svg\]\:h-auto svg {
5278
+ height: auto;
5279
+ }
5280
+
5281
+ .\[\&_svg\]\:max-w-full svg {
5282
+ max-width: 100%;
5283
+ }
5284
+
5226
5285
  .\[\&\:\:-webkit-search-cancel-button\]\:hidden::-webkit-search-cancel-button {
5227
5286
  display: none;
5228
5287
  }
@@ -0,0 +1,22 @@
1
+ import { ReactNode } from 'react';
2
+ import { Config, NavigationTree, RouteItem } from '../core/types';
3
+ import { OpenAPISpec } from '../openapi/lib/utils';
4
+ import { RuntimeSlots } from '../slots';
5
+ export type ClarifyShellProps = {
6
+ config: Config;
7
+ routes: RouteItem[];
8
+ navigation?: NavigationTree;
9
+ openApis: Record<string, OpenAPISpec>;
10
+ runtimeSlots?: RuntimeSlots;
11
+ themeEditor?: boolean;
12
+ children?: ReactNode;
13
+ };
14
+ /**
15
+ * Shared provider chain used by both client-side render and server-side
16
+ * renderToHTML. Wraps AppShell with ConfigContext → OpenApisContext →
17
+ * ThemeProvider → ThemeRoot.
18
+ *
19
+ * The outer Router (BrowserRouter / StaticRouter) is left to the caller
20
+ * so each entry point can supply the correct router variant.
21
+ */
22
+ export declare function ClarifyShell(props: ClarifyShellProps): import("react").JSX.Element;
package/output/server.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_PageActions = require("./PageActions-1RDCHcUY.cjs");
3
- const require_ThemeRoot = require("./ThemeRoot-DYS-lcK-.cjs");
2
+ const require_PageActions = require("./PageActions-yycPlNyL.cjs");
3
+ const require_ClarifyShell = require("./ClarifyShell-DNN5erFD.cjs");
4
4
  let react = require("react");
5
5
  let react_router_dom = require("react-router-dom");
6
6
  let react_jsx_runtime = require("react/jsx-runtime");
@@ -12,27 +12,18 @@ let react_dom_server = require("react-dom/server");
12
12
  * 返回 `div#root` 内部的 HTML,由 Clarify CLI 组装为完整的 HTML 文档。
13
13
  */
14
14
  function renderToHTML(options) {
15
- const { config, routes, navigation, openApis = {}, bannerComponent, footerComponent, url, themeEditor = false } = options;
15
+ const { config, routes, navigation, openApis = {}, runtimeSlots, url, themeEditor = false } = options;
16
16
  const location = require_PageActions.prefixHref(url, config.routePrefix);
17
17
  return (0, react_dom_server.renderToString)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.StrictMode, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_router_dom.StaticRouter, {
18
18
  basename: config.routePrefix,
19
19
  location,
20
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PageActions.ConfigContext.Provider, {
21
- value: config,
22
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PageActions.OpenApisContext.Provider, {
23
- value: openApis,
24
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PageActions.ThemeProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ThemeRoot.ThemeRoot, {
25
- theme: config.theme,
26
- themeEditor,
27
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ThemeRoot.AppShell, {
28
- config,
29
- routes,
30
- navigation: navigation ?? [],
31
- bannerComponent,
32
- footerComponent
33
- })
34
- }) })
35
- })
20
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ClarifyShell.ClarifyShell, {
21
+ config,
22
+ routes,
23
+ navigation,
24
+ openApis,
25
+ runtimeSlots,
26
+ themeEditor
36
27
  })
37
28
  }) }));
38
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.cjs","names":[],"sources":["../source/runtime/server.tsx"],"sourcesContent":["import { StrictMode } from 'react'\nimport { renderToString } from 'react-dom/server'\nimport { StaticRouter } from 'react-router-dom'\n\nimport { AppShell } from '../app/AppShell'\nimport { ConfigContext, OpenApisContext } from '../context'\nimport { ThemeProvider } from '../theme/ThemeProvider'\nimport { ThemeRoot } from '../theme/ThemeRoot'\nimport type { ServerRenderOptions } from '../types'\nimport { prefixHref } from '../utils/href'\n\n/**\n * Clarify 服务端渲染入口。\n * 由 @clarify-labs/cli 在构建时调用,为每条路由生成 React HTML 片段。\n * 返回 `div#root` 内部的 HTML,由 Clarify CLI 组装为完整的 HTML 文档。\n */\nexport function renderToHTML(options: ServerRenderOptions): string {\n const { config, routes, navigation, openApis = {}, bannerComponent, footerComponent, url, themeEditor = false } = options\n const location = prefixHref(url, config.routePrefix)\n\n return renderToString(\n <StrictMode>\n <StaticRouter basename={config.routePrefix} location={location}>\n <ConfigContext.Provider value={config}>\n <OpenApisContext.Provider value={openApis}>\n <ThemeProvider>\n <ThemeRoot theme={config.theme} themeEditor={themeEditor}>\n <AppShell config={config} routes={routes} navigation={navigation ?? []} bannerComponent={bannerComponent} footerComponent={footerComponent} />\n </ThemeRoot>\n </ThemeProvider>\n </OpenApisContext.Provider>\n </ConfigContext.Provider>\n </StaticRouter>\n </StrictMode>\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAgBA,SAAgB,aAAa,SAAsC;CACjE,MAAM,EAAE,QAAQ,QAAQ,YAAY,WAAW,CAAC,GAAG,iBAAiB,iBAAiB,KAAK,cAAc,UAAU;CAClH,MAAM,WAAW,oBAAA,WAAW,KAAK,OAAO,WAAW;CAEnD,QAAA,GAAA,iBAAA,gBACE,iBAAA,GAAA,kBAAA,KAAC,MAAA,YAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,iBAAA,cAAD;EAAc,UAAU,OAAO;EAAuB;YACpD,iBAAA,GAAA,kBAAA,KAAC,oBAAA,cAAc,UAAf;GAAwB,OAAO;aAC7B,iBAAA,GAAA,kBAAA,KAAC,oBAAA,gBAAgB,UAAjB;IAA0B,OAAO;cAC/B,iBAAA,GAAA,kBAAA,KAAC,oBAAA,eAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,kBAAA,WAAD;KAAW,OAAO,OAAO;KAAoB;eAC3C,iBAAA,GAAA,kBAAA,KAAC,kBAAA,UAAD;MAAkB;MAAgB;MAAQ,YAAY,cAAc,CAAC;MAAoB;MAAkC;KAAkB,CAAA;IACpI,CAAA,EACE,CAAA;GACS,CAAA;EACJ,CAAA;CACZ,CAAA,EACJ,CAAA,CACd;AACF"}
1
+ {"version":3,"file":"server.cjs","names":[],"sources":["../source/runtime/server.tsx"],"sourcesContent":["import { StrictMode } from 'react'\nimport { renderToString } from 'react-dom/server'\nimport { StaticRouter } from 'react-router-dom'\n\nimport type { ServerRenderOptions } from '../types'\nimport { prefixHref } from '../utils/href'\n\nimport { ClarifyShell } from './ClarifyShell'\n\n/**\n * Clarify 服务端渲染入口。\n * 由 @clarify-labs/cli 在构建时调用,为每条路由生成 React HTML 片段。\n * 返回 `div#root` 内部的 HTML,由 Clarify CLI 组装为完整的 HTML 文档。\n */\nexport function renderToHTML(options: ServerRenderOptions): string {\n const { config, routes, navigation, openApis = {}, runtimeSlots, url, themeEditor = false } = options\n const location = prefixHref(url, config.routePrefix)\n\n return renderToString(\n <StrictMode>\n <StaticRouter basename={config.routePrefix} location={location}>\n <ClarifyShell\n config={config}\n routes={routes}\n navigation={navigation}\n openApis={openApis}\n runtimeSlots={runtimeSlots}\n themeEditor={themeEditor}\n />\n </StaticRouter>\n </StrictMode>\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,SAAgB,aAAa,SAAsC;CACjE,MAAM,EAAE,QAAQ,QAAQ,YAAY,WAAW,CAAC,GAAG,cAAc,KAAK,cAAc,UAAU;CAC9F,MAAM,WAAW,oBAAA,WAAW,KAAK,OAAO,WAAW;CAEnD,QAAA,GAAA,iBAAA,gBACE,iBAAA,GAAA,kBAAA,KAAC,MAAA,YAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,iBAAA,cAAD;EAAc,UAAU,OAAO;EAAuB;YACpD,iBAAA,GAAA,kBAAA,KAAC,qBAAA,cAAD;GACU;GACA;GACI;GACF;GACI;GACD;EACd,CAAA;CACW,CAAA,EACJ,CAAA,CACd;AACF"}
package/output/server.js CHANGED
@@ -1,5 +1,5 @@
1
- import { A as OpenApisContext, O as ConfigContext, T as prefixHref, m as ThemeProvider } from "./PageActions-yoDRjkq8.js";
2
- import { c as AppShell, t as ThemeRoot } from "./ThemeRoot-CLa0yvRQ.js";
1
+ import { E as prefixHref } from "./PageActions-DR0asnKH.js";
2
+ import { t as ClarifyShell } from "./ClarifyShell-BxB_6Uhd.js";
3
3
  import { StrictMode } from "react";
4
4
  import { StaticRouter } from "react-router-dom";
5
5
  import { jsx } from "react/jsx-runtime";
@@ -11,27 +11,18 @@ import { renderToString } from "react-dom/server";
11
11
  * 返回 `div#root` 内部的 HTML,由 Clarify CLI 组装为完整的 HTML 文档。
12
12
  */
13
13
  function renderToHTML(options) {
14
- const { config, routes, navigation, openApis = {}, bannerComponent, footerComponent, url, themeEditor = false } = options;
14
+ const { config, routes, navigation, openApis = {}, runtimeSlots, url, themeEditor = false } = options;
15
15
  const location = prefixHref(url, config.routePrefix);
16
16
  return renderToString(/* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsx(StaticRouter, {
17
17
  basename: config.routePrefix,
18
18
  location,
19
- children: /* @__PURE__ */ jsx(ConfigContext.Provider, {
20
- value: config,
21
- children: /* @__PURE__ */ jsx(OpenApisContext.Provider, {
22
- value: openApis,
23
- children: /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(ThemeRoot, {
24
- theme: config.theme,
25
- themeEditor,
26
- children: /* @__PURE__ */ jsx(AppShell, {
27
- config,
28
- routes,
29
- navigation: navigation ?? [],
30
- bannerComponent,
31
- footerComponent
32
- })
33
- }) })
34
- })
19
+ children: /* @__PURE__ */ jsx(ClarifyShell, {
20
+ config,
21
+ routes,
22
+ navigation,
23
+ openApis,
24
+ runtimeSlots,
25
+ themeEditor
35
26
  })
36
27
  }) }));
37
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","names":[],"sources":["../source/runtime/server.tsx"],"sourcesContent":["import { StrictMode } from 'react'\nimport { renderToString } from 'react-dom/server'\nimport { StaticRouter } from 'react-router-dom'\n\nimport { AppShell } from '../app/AppShell'\nimport { ConfigContext, OpenApisContext } from '../context'\nimport { ThemeProvider } from '../theme/ThemeProvider'\nimport { ThemeRoot } from '../theme/ThemeRoot'\nimport type { ServerRenderOptions } from '../types'\nimport { prefixHref } from '../utils/href'\n\n/**\n * Clarify 服务端渲染入口。\n * 由 @clarify-labs/cli 在构建时调用,为每条路由生成 React HTML 片段。\n * 返回 `div#root` 内部的 HTML,由 Clarify CLI 组装为完整的 HTML 文档。\n */\nexport function renderToHTML(options: ServerRenderOptions): string {\n const { config, routes, navigation, openApis = {}, bannerComponent, footerComponent, url, themeEditor = false } = options\n const location = prefixHref(url, config.routePrefix)\n\n return renderToString(\n <StrictMode>\n <StaticRouter basename={config.routePrefix} location={location}>\n <ConfigContext.Provider value={config}>\n <OpenApisContext.Provider value={openApis}>\n <ThemeProvider>\n <ThemeRoot theme={config.theme} themeEditor={themeEditor}>\n <AppShell config={config} routes={routes} navigation={navigation ?? []} bannerComponent={bannerComponent} footerComponent={footerComponent} />\n </ThemeRoot>\n </ThemeProvider>\n </OpenApisContext.Provider>\n </ConfigContext.Provider>\n </StaticRouter>\n </StrictMode>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,SAAgB,aAAa,SAAsC;CACjE,MAAM,EAAE,QAAQ,QAAQ,YAAY,WAAW,CAAC,GAAG,iBAAiB,iBAAiB,KAAK,cAAc,UAAU;CAClH,MAAM,WAAW,WAAW,KAAK,OAAO,WAAW;CAEnD,OAAO,eACL,oBAAC,YAAD,EAAA,UACE,oBAAC,cAAD;EAAc,UAAU,OAAO;EAAuB;YACpD,oBAAC,cAAc,UAAf;GAAwB,OAAO;aAC7B,oBAAC,gBAAgB,UAAjB;IAA0B,OAAO;cAC/B,oBAAC,eAAD,EAAA,UACE,oBAAC,WAAD;KAAW,OAAO,OAAO;KAAoB;eAC3C,oBAAC,UAAD;MAAkB;MAAgB;MAAQ,YAAY,cAAc,CAAC;MAAoB;MAAkC;KAAkB,CAAA;IACpI,CAAA,EACE,CAAA;GACS,CAAA;EACJ,CAAA;CACZ,CAAA,EACJ,CAAA,CACd;AACF"}
1
+ {"version":3,"file":"server.js","names":[],"sources":["../source/runtime/server.tsx"],"sourcesContent":["import { StrictMode } from 'react'\nimport { renderToString } from 'react-dom/server'\nimport { StaticRouter } from 'react-router-dom'\n\nimport type { ServerRenderOptions } from '../types'\nimport { prefixHref } from '../utils/href'\n\nimport { ClarifyShell } from './ClarifyShell'\n\n/**\n * Clarify 服务端渲染入口。\n * 由 @clarify-labs/cli 在构建时调用,为每条路由生成 React HTML 片段。\n * 返回 `div#root` 内部的 HTML,由 Clarify CLI 组装为完整的 HTML 文档。\n */\nexport function renderToHTML(options: ServerRenderOptions): string {\n const { config, routes, navigation, openApis = {}, runtimeSlots, url, themeEditor = false } = options\n const location = prefixHref(url, config.routePrefix)\n\n return renderToString(\n <StrictMode>\n <StaticRouter basename={config.routePrefix} location={location}>\n <ClarifyShell\n config={config}\n routes={routes}\n navigation={navigation}\n openApis={openApis}\n runtimeSlots={runtimeSlots}\n themeEditor={themeEditor}\n />\n </StaticRouter>\n </StrictMode>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAcA,SAAgB,aAAa,SAAsC;CACjE,MAAM,EAAE,QAAQ,QAAQ,YAAY,WAAW,CAAC,GAAG,cAAc,KAAK,cAAc,UAAU;CAC9F,MAAM,WAAW,WAAW,KAAK,OAAO,WAAW;CAEnD,OAAO,eACL,oBAAC,YAAD,EAAA,UACE,oBAAC,cAAD;EAAc,UAAU,OAAO;EAAuB;YACpD,oBAAC,cAAD;GACU;GACA;GACI;GACF;GACI;GACD;EACd,CAAA;CACW,CAAA,EACJ,CAAA,CACd;AACF"}
@@ -1,5 +1,4 @@
1
1
  import { Pagefind } from './types';
2
2
  export declare function pagefindCacheKey(routePrefix: string, locale: string | undefined): string;
3
- export declare function logSearchDebug(message: string, data?: Record<string, unknown>): void;
4
3
  export declare function loadPagefind(routePrefix: string, locale: string | undefined): Promise<Pagefind | null>;
5
4
  export declare function normalizePagefindUrl(url: string, routePrefix: string): string;
@@ -0,0 +1,58 @@
1
+ import { ComponentType, ReactNode } from 'react';
2
+ import { RouteItem } from '../core/types';
3
+ import { UISlotName } from './types';
4
+ /**
5
+ * One registered slot component, as compiled by the CLI into
6
+ * `virtual:clarify/slots`.
7
+ *
8
+ * `component` is a lazy import factory `() => import('path')`. On the client
9
+ * it is passed to `React.lazy`. During SSR the factory is pre-resolved and
10
+ * the resulting component is stored in `_resolved`, which the renderer uses
11
+ * directly (no Suspense needed for `renderToString`).
12
+ */
13
+ export type RuntimeSlotEntry = {
14
+ /** Plugin that registered this component, used as a stable render key. */
15
+ plugin: string;
16
+ /** Lazy import factory — `() => import('path')`. Set by CLI virtual module. */
17
+ component: () => Promise<{
18
+ default: ComponentType;
19
+ }>;
20
+ /** @internal Pre-resolved component set by SSR before {@link renderToHTML}. */
21
+ _resolved?: ComponentType;
22
+ };
23
+ /** Registry keyed by slot name. */
24
+ export type RuntimeSlots = Partial<Record<UISlotName, RuntimeSlotEntry[]>>;
25
+ type RuntimeSlotsContextValue = {
26
+ slots: RuntimeSlots;
27
+ route?: RouteItem;
28
+ };
29
+ export declare const RuntimeSlotsContext: import('react').Context<RuntimeSlotsContextValue>;
30
+ type RuntimeSlotsProviderProps = {
31
+ slots?: RuntimeSlots;
32
+ route?: RouteItem;
33
+ children: ReactNode;
34
+ };
35
+ /**
36
+ * Makes the compiled slot registry and the current route available to every
37
+ * {@link RuntimeSlot} in the tree. Mounted once near the top of `AppShell`.
38
+ */
39
+ export declare function RuntimeSlotsProvider(arg0: RuntimeSlotsProviderProps): ReactNode;
40
+ type RuntimeSlotProps = {
41
+ name: UISlotName;
42
+ /** Built-in default component for replacement slots. */
43
+ default?: ComponentType;
44
+ };
45
+ /**
46
+ * Renders plugin components registered for a slot, in registration order.
47
+ *
48
+ * For extension slots (*.before/*.after), renders all plugin components.
49
+ * For replacement slots (*.replace), renders only the last registered plugin
50
+ * component (if any), and passes the default component through context.
51
+ *
52
+ * Each component is loaded via the import factory. If `_resolved` is set
53
+ * (SSR pre-resolution), the component is rendered synchronously for
54
+ * compatibility with `renderToString`. Otherwise, `React.lazy` + `Suspense`
55
+ * is used for client-side code-splitting.
56
+ */
57
+ export declare function RuntimeSlot(arg0: RuntimeSlotProps): ReactNode;
58
+ export {};
@@ -0,0 +1,20 @@
1
+ import { ReactNode } from 'react';
2
+ import { UISlotName, SlotContext } from './types';
3
+ export type { UISlotName, SlotContext };
4
+ type SlotProviderProps = {
5
+ value: SlotContext;
6
+ children: ReactNode;
7
+ };
8
+ /**
9
+ * Provides an isolated {@link SlotContext} for a single slot component.
10
+ * `RuntimeSlot` wraps every rendered slot component with this provider.
11
+ */
12
+ export declare function SlotProvider(arg0: SlotProviderProps): ReactNode;
13
+ /**
14
+ * Reads the current slot context.
15
+ *
16
+ * Must be called inside a slot component (or a descendant). Calling it outside a
17
+ * slot provider throws, which helps plugin authors notice that the component was
18
+ * not mounted through a Clarify slot.
19
+ */
20
+ export declare function useSlot(): SlotContext;
@@ -0,0 +1,5 @@
1
+ export { SlotProvider, useSlot } from './context';
2
+ export type { SlotContext, UISlotName } from './context';
3
+ export { RuntimeSlot, RuntimeSlotsProvider, RuntimeSlotsContext } from './RuntimeSlot';
4
+ export type { RuntimeSlotEntry, RuntimeSlots } from './RuntimeSlot';
5
+ export type { UISlotRegistration } from './types';
@@ -0,0 +1,50 @@
1
+ import { ComponentType } from 'react';
2
+ import { RouteItem } from '../core/types';
3
+ /**
4
+ * Stable runtime UI slot positions.
5
+ *
6
+ * The name is a dot-path `${scope}.${path}.${position}`:
7
+ * - `*.before`: Extension slot, plugin components render before default
8
+ * - `*.after`: Extension slot, plugin components render after default
9
+ * - `*.replace`: Replacement slot, plugin component replaces default
10
+ */
11
+ export type UISlotName = 'page.footer.before' | 'page.banner.replace' | 'page.footer.replace';
12
+ /**
13
+ * Context exposed to a slot component through the `useSlot` hook.
14
+ *
15
+ * Slot components never receive Clarify context through props. Instead they read
16
+ * everything they need from this hook, which keeps slot components as ordinary
17
+ * React components and lets the slot context grow without changing signatures.
18
+ */
19
+ export type SlotContext = {
20
+ /** The slot the current component is mounted into. */
21
+ name: UISlotName;
22
+ /** Name of the plugin that registered the current slot component. */
23
+ plugin: string;
24
+ /** Current route, when a content route is active. */
25
+ route?: RouteItem;
26
+ /** Current locale, for example `zh-CN` or `en-US`. */
27
+ locale?: string;
28
+ /** Built-in default component for replacement slots. */
29
+ DefaultComponent?: ComponentType;
30
+ };
31
+ /**
32
+ * A runtime UI extension declared by a plugin. The CLI compiles every
33
+ * registration into `virtual:clarify/slots`.
34
+ */
35
+ export type UISlotRegistration = {
36
+ /** Target slot position. */
37
+ name: UISlotName;
38
+ /**
39
+ * Module path of the React component to mount.
40
+ *
41
+ * Use `/` prefix to reference files relative to the project root, for
42
+ * example:
43
+ * ```
44
+ * component: '/source/plugins/custom-footer.tsx'
45
+ * ```
46
+ *
47
+ * The component is imported as a default export.
48
+ */
49
+ component: string;
50
+ };
@@ -0,0 +1,7 @@
1
+ import { LocalizedText } from '../core/types';
2
+ /**
3
+ * Resolve a localized text value for the given locale.
4
+ * Falls back to the fallback locale, then the first available value,
5
+ * then an empty string.
6
+ */
7
+ export declare function resolveLocalizedText(text: LocalizedText, locale?: string, fallbackLocale?: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clarify-labs/renderer",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "license": "AGPL-3.0-only",
5
5
  "type": "module",
6
6
  "repository": {
@@ -54,7 +54,9 @@
54
54
  "build": "vite build",
55
55
  "lint": "eslint source/",
56
56
  "lint:fix": "eslint source/ --fix",
57
- "typecheck": "tsc -p tsconfig.json --noEmit"
57
+ "typecheck": "tsc -p tsconfig.json --noEmit",
58
+ "test": "vitest run",
59
+ "test:watch": "vitest"
58
60
  },
59
61
  "peerDependencies": {
60
62
  "react": "^19.0.0",
@@ -72,7 +74,8 @@
72
74
  "tailwindcss": "^4.1.11",
73
75
  "typescript": "^5.8.3",
74
76
  "vite": "^8.0.15",
75
- "vite-plugin-dts": "^4.5.4"
77
+ "vite-plugin-dts": "^4.5.4",
78
+ "vitest": "^4.1.9"
76
79
  },
77
80
  "dependencies": {
78
81
  "@headlessui/react": "^2.2.10",
@@ -82,8 +85,10 @@
82
85
  "framer-motion": "^12.40.0",
83
86
  "github-slugger": "^2.0.0",
84
87
  "lucide-react": "^1.20.0",
88
+ "mermaid": "^11.4.0",
85
89
  "openapi-types": "^12.1.3",
86
90
  "react-markdown": "^10.1.0",
91
+ "react-zoom-pan-pinch": "^4.0.3",
87
92
  "remark-gfm": "^4.0.1",
88
93
  "zustand": "^5.0.14"
89
94
  }