create-zudo-doc 0.2.20 → 0.2.22
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/features/image-enlarge.d.ts +10 -2
- package/dist/features/image-enlarge.js +10 -2
- package/dist/scaffold.js +22 -22
- package/dist/zfb-config-gen.d.ts +16 -10
- package/dist/zfb-config-gen.js +34 -239
- package/package.json +1 -1
- package/templates/base/pages/lib/_body-end-islands.tsx +6 -13
- package/templates/base/pages/lib/_category-nav.tsx +30 -115
- package/templates/base/pages/lib/_category-tree-nav.tsx +38 -65
- package/templates/base/pages/lib/_compose-meta-title.ts +2 -6
- package/templates/base/pages/lib/_doc-body-end.tsx +3 -35
- package/templates/base/pages/lib/_doc-content-header.tsx +10 -111
- package/templates/base/pages/lib/_doc-history-area.tsx +19 -211
- package/templates/base/pages/lib/_doc-metainfo-area.tsx +10 -113
- package/templates/base/pages/lib/_doc-page-renderer.tsx +22 -183
- package/templates/base/pages/lib/_doc-page-shell.tsx +17 -251
- package/templates/base/pages/lib/_doc-pager.tsx +4 -74
- package/templates/base/pages/lib/_doc-route-entries.ts +43 -177
- package/templates/base/pages/lib/_doc-route-paths.ts +16 -101
- package/templates/base/pages/lib/_doc-tags-area.tsx +14 -77
- package/templates/base/pages/lib/_footer-with-defaults.tsx +37 -225
- package/templates/base/pages/lib/_frontmatter-preview-data.ts +5 -31
- package/templates/base/pages/lib/_head-with-defaults.tsx +13 -138
- package/templates/base/pages/lib/_header-with-defaults.tsx +24 -324
- package/templates/base/pages/lib/_inline-version-switcher.tsx +16 -78
- package/templates/base/pages/lib/_nav-data-prep.ts +32 -51
- package/templates/base/pages/lib/_nav-source-cache.ts +12 -57
- package/templates/base/pages/lib/_nav-source-docs.ts +33 -233
- package/templates/base/pages/lib/_search-widget-script.ts +2 -470
- package/templates/base/pages/lib/_search-widget.tsx +9 -195
- package/templates/base/pages/lib/_sidebar-prepaint.tsx +6 -47
- package/templates/base/pages/lib/_sidebar-with-defaults.tsx +16 -118
- package/templates/base/pages/lib/_site-tree-nav.tsx +29 -80
- package/templates/base/pages/lib/doc-page-props.ts +26 -44
- package/templates/base/pages/lib/locale-merge.ts +32 -145
- package/templates/base/pages/lib/route-enumerators.ts +52 -286
- package/templates/base/pages/robots.txt.tsx +2 -26
- package/templates/base/src/components/ai-chat-modal.tsx +9 -8
- package/templates/base/src/components/doc-history.tsx +9 -8
- package/templates/base/src/components/image-enlarge.tsx +11 -8
- package/templates/base/src/components/sidebar-toggle.tsx +6 -170
- package/templates/base/src/components/sidebar-tree.tsx +6 -548
- package/templates/base/src/components/site-tree-nav.tsx +6 -220
- package/templates/base/src/config/color-scheme-utils.ts +34 -158
- package/templates/base/src/config/i18n.ts +9 -0
- package/templates/base/src/config/z-index-tokens.ts +5 -4
- package/templates/base/src/styles/global.css +5 -579
- package/templates/base/src/utils/base.ts +1 -1
- package/templates/base/src/utils/docs.ts +47 -16
- package/templates/base/src/utils/github.ts +12 -9
- package/templates/base/src/utils/nav-scope.ts +13 -42
- package/templates/base/src/utils/sidebar.ts +18 -86
- package/templates/base/src/utils/slug.ts +10 -53
- package/templates/base/src/utils/smart-break.tsx +12 -120
- package/templates/base/src/utils/tags.ts +25 -68
- package/templates/features/bodyFootUtil/files/src/utils/github.ts +12 -9
- package/templates/features/designTokenPanel/files/src/lib/design-token-panel-bootstrap.ts +13 -39
- package/templates/features/docHistory/files/src/components/doc-history.tsx +8 -636
- package/templates/features/docHistory/files/src/types/doc-history.ts +7 -23
- package/templates/features/docTags/files/pages/lib/_tag-pages.tsx +35 -201
- package/templates/features/imageEnlarge/files/src/components/image-enlarge.tsx +8 -269
- package/templates/features/sidebarToggle/files/src/components/desktop-sidebar-toggle.tsx +6 -99
- package/templates/features/tagGovernance/files/scripts/tags-audit.ts +67 -515
- package/templates/features/tauri/files/src-tauri/capabilities/default.json +1 -4
- package/templates/features/tauri/files/src-tauri/tauri.conf.json +1 -1
- package/templates/features/tauriDev/files/src-tauri-dev/capabilities/default.json +1 -1
- package/templates/features/versioning/files/pages/lib/_versions-page.tsx +21 -73
- package/templates/base/plugins/connect-adapter.mjs +0 -169
- package/templates/base/plugins/search-index-plugin.mjs +0 -66
- package/templates/base/scripts/gen-z-index.mjs +0 -157
- package/templates/base/src/components/mermaid-enlarge.tsx +0 -490
- package/templates/features/claudeResources/files/plugins/claude-resources-plugin.mjs +0 -47
- package/templates/features/docHistory/files/plugins/doc-history-plugin.mjs +0 -111
- package/templates/features/llmsTxt/files/plugins/llms-txt-plugin.mjs +0 -93
|
@@ -42,6 +42,11 @@
|
|
|
42
42
|
above (line 11); the safelist import above generates the component utilities
|
|
43
43
|
its headings/links/etc. depend on. */
|
|
44
44
|
@import "@takazudo/zudo-doc/content.css";
|
|
45
|
+
/* Non-island feature CSS (code block buttons, syntect light-dark token rule,
|
|
46
|
+
.zd-html-preview-code, KaTeX, sidebar toggle geometry, view-transition chrome,
|
|
47
|
+
.ai-chat-md, .zd-enlarge*, .zd-mermaid*).
|
|
48
|
+
Shipped by @takazudo/zudo-doc as single source of truth. See zudolab/zudo-doc#2331. */
|
|
49
|
+
@import "@takazudo/zudo-doc/features.css";
|
|
45
50
|
/* @slot:global-css:imports */
|
|
46
51
|
|
|
47
52
|
/* ========================================
|
|
@@ -308,234 +313,6 @@ body {
|
|
|
308
313
|
}
|
|
309
314
|
}
|
|
310
315
|
|
|
311
|
-
/* ========================================
|
|
312
|
-
* Code block buttons (copy + word wrap)
|
|
313
|
-
* ======================================== */
|
|
314
|
-
|
|
315
|
-
.code-block-wrapper {
|
|
316
|
-
position: relative;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
pre[class^="syntect-"].word-wrap {
|
|
320
|
-
overflow-x: hidden;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
pre[class^="syntect-"].word-wrap code {
|
|
324
|
-
white-space: pre-wrap;
|
|
325
|
-
overflow-wrap: anywhere;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
.code-block-sr-announce {
|
|
329
|
-
position: absolute;
|
|
330
|
-
width: 1px;
|
|
331
|
-
height: 1px;
|
|
332
|
-
overflow: hidden;
|
|
333
|
-
clip: rect(0, 0, 0, 0);
|
|
334
|
-
white-space: nowrap;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
.code-buttons {
|
|
338
|
-
position: absolute;
|
|
339
|
-
top: var(--spacing-hsp-sm);
|
|
340
|
-
right: var(--spacing-hsp-sm);
|
|
341
|
-
display: flex;
|
|
342
|
-
gap: var(--spacing-hsp-2xs);
|
|
343
|
-
opacity: 0;
|
|
344
|
-
transition: opacity 0.15s;
|
|
345
|
-
z-index: var(--z-index-local-1);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
.code-block-wrapper:hover .code-buttons,
|
|
349
|
-
.code-block-wrapper:focus-within .code-buttons {
|
|
350
|
-
opacity: 1;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
.code-btn {
|
|
354
|
-
display: flex;
|
|
355
|
-
align-items: center;
|
|
356
|
-
justify-content: center;
|
|
357
|
-
width: var(--spacing-hsp-2xl);
|
|
358
|
-
height: var(--spacing-hsp-2xl);
|
|
359
|
-
padding: 0;
|
|
360
|
-
border: 1px solid var(--color-muted);
|
|
361
|
-
border-radius: var(--radius-lg);
|
|
362
|
-
background-color: var(--color-surface);
|
|
363
|
-
color: var(--color-fg);
|
|
364
|
-
cursor: pointer;
|
|
365
|
-
transition:
|
|
366
|
-
color 0.15s,
|
|
367
|
-
border-color 0.15s,
|
|
368
|
-
background-color 0.15s;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
.code-btn:hover {
|
|
372
|
-
color: var(--color-fg);
|
|
373
|
-
border-color: var(--color-fg);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
.code-btn .code-icon {
|
|
377
|
-
width: var(--spacing-hsp-lg);
|
|
378
|
-
height: var(--spacing-hsp-lg);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/* Copy: icon swap */
|
|
382
|
-
.code-btn-copy .code-icon-check {
|
|
383
|
-
display: none;
|
|
384
|
-
}
|
|
385
|
-
.code-btn-copy .code-icon-copy {
|
|
386
|
-
display: block;
|
|
387
|
-
}
|
|
388
|
-
.code-btn-copy.copied .code-icon-check {
|
|
389
|
-
display: block;
|
|
390
|
-
color: var(--color-success);
|
|
391
|
-
}
|
|
392
|
-
.code-btn-copy.copied .code-icon-copy {
|
|
393
|
-
display: none;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/* Word wrap active state */
|
|
397
|
-
.code-btn-wrap.active {
|
|
398
|
-
color: var(--color-accent);
|
|
399
|
-
border-color: var(--color-accent);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
@media (scripting: none) {
|
|
403
|
-
.code-buttons {
|
|
404
|
-
display: none;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/* ========================================
|
|
409
|
-
* Code-block syntax-highlight token color rule
|
|
410
|
-
* ======================================== */
|
|
411
|
-
|
|
412
|
-
/* Build-time: zfb's Rust pipeline runs SyntectPlugin and emits
|
|
413
|
-
* <pre class="syntect-..."> with inline style="color:#hex" on every token
|
|
414
|
-
* span. The inline hex is the desired token color — this rule must NOT
|
|
415
|
-
* override it (so: NO !important on `color`).
|
|
416
|
-
*
|
|
417
|
-
* Runtime (design-token-tweak panel, when enabled): Shiki re-highlights on
|
|
418
|
-
* demand and emits spans with inline style="--shiki-light:#X;--shiki-dark:#Y"
|
|
419
|
-
* — CSS custom properties only, no `color` declaration — depending on this
|
|
420
|
-
* rule to resolve light-dark(var(--shiki-light), var(--shiki-dark)) to the
|
|
421
|
-
* active theme. Shiki spans have no inline `color`, so the rule applies
|
|
422
|
-
* without needing !important. */
|
|
423
|
-
[data-theme] .shiki,
|
|
424
|
-
[data-theme] .shiki span,
|
|
425
|
-
[data-theme] pre[class^="syntect-"],
|
|
426
|
-
[data-theme] pre[class^="syntect-"] span {
|
|
427
|
-
color: light-dark(var(--shiki-light), var(--shiki-dark));
|
|
428
|
-
background-color: light-dark(var(--shiki-light-bg), var(--shiki-dark-bg));
|
|
429
|
-
font-style: light-dark(
|
|
430
|
-
var(--shiki-light-font-style, inherit),
|
|
431
|
-
var(--shiki-dark-font-style, inherit)
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/* HtmlPreview component — Shiki code blocks
|
|
436
|
-
* Token colors inherit from the global [data-theme] .shiki rule above.
|
|
437
|
-
* These rules only adjust layout and background for the preview context. */
|
|
438
|
-
.zd-html-preview-code pre.shiki {
|
|
439
|
-
margin: 0;
|
|
440
|
-
padding: 0.75rem;
|
|
441
|
-
font-size: 0.875rem;
|
|
442
|
-
line-height: 1.6;
|
|
443
|
-
overflow-x: auto;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
.zd-html-preview-code pre.shiki code {
|
|
447
|
-
font-family: var(--font-mono);
|
|
448
|
-
white-space: pre;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/* ========================================
|
|
452
|
-
* Code block line highlighting
|
|
453
|
-
* ======================================== */
|
|
454
|
-
|
|
455
|
-
/* Line highlighting via {1,3-5} meta syntax.
|
|
456
|
-
* zfb emits data-line-highlight="true" on the <span class="line"> element
|
|
457
|
-
* (verified empirically at next.13). The .highlighted class form is kept for
|
|
458
|
-
* forward-compat in case a future zfb version emits both. */
|
|
459
|
-
pre[class^="syntect-"] .line.highlighted,
|
|
460
|
-
pre[class^="syntect-"] [data-line-highlight="true"] {
|
|
461
|
-
background-color: color-mix(in srgb, var(--color-accent) 15%, transparent);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/* Word highlighting via /word/ meta syntax */
|
|
465
|
-
pre[class^="syntect-"] .line .highlighted-word {
|
|
466
|
-
background-color: color-mix(in srgb, var(--color-accent) 25%, transparent);
|
|
467
|
-
border-bottom: 1px solid var(--color-accent);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
/* ========================================
|
|
471
|
-
* Code block titles
|
|
472
|
-
* ======================================== */
|
|
473
|
-
|
|
474
|
-
.code-block-container {
|
|
475
|
-
margin-top: 1em;
|
|
476
|
-
margin-bottom: 1em;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
.code-block-title {
|
|
480
|
-
font-family: var(--font-mono);
|
|
481
|
-
font-size: var(--text-small);
|
|
482
|
-
color: var(--color-muted);
|
|
483
|
-
background-color: var(--color-code-bg);
|
|
484
|
-
border: 1px solid var(--color-muted);
|
|
485
|
-
border-bottom: none;
|
|
486
|
-
padding: var(--spacing-vsp-2xs) var(--spacing-hsp-lg);
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
.code-block-container pre[class^="syntect-"] {
|
|
490
|
-
margin-top: 0 !important;
|
|
491
|
-
border-top-left-radius: 0;
|
|
492
|
-
border-top-right-radius: 0;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
/* ========================================
|
|
496
|
-
* CodeGroup raw-code panels (codeTabs Option A)
|
|
497
|
-
*
|
|
498
|
-
* zfb's :::code-group emits <CodeGroup tabs={[...]}> with one
|
|
499
|
-
* <pre data-lang="…">{RAW text}</pre> child per fence. These <pre> elements
|
|
500
|
-
* are NOT syntect-highlighted (the Rust pipeline doesn't highlight inside
|
|
501
|
-
* code-group fences), so they get no `.syntect-*` class. Apply explicit
|
|
502
|
-
* code-block visual treatment via tokens to match the syntect-highlighted
|
|
503
|
-
* code blocks surrounding them.
|
|
504
|
-
* ======================================== */
|
|
505
|
-
|
|
506
|
-
.code-group-panel pre[data-lang] {
|
|
507
|
-
font-family: var(--font-mono);
|
|
508
|
-
font-size: var(--text-small);
|
|
509
|
-
line-height: var(--leading-relaxed);
|
|
510
|
-
background-color: var(--color-code-bg);
|
|
511
|
-
color: var(--color-code-fg);
|
|
512
|
-
padding: var(--spacing-vsp-xs) var(--spacing-hsp-lg);
|
|
513
|
-
overflow-x: auto;
|
|
514
|
-
border-radius: 0 0 var(--radius-DEFAULT) var(--radius-DEFAULT);
|
|
515
|
-
margin: 0;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/* KaTeX math equations */
|
|
519
|
-
.katex {
|
|
520
|
-
font-size: 1.1em;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
.katex-display {
|
|
524
|
-
margin: var(--spacing-vsp-md) 0;
|
|
525
|
-
overflow-x: auto;
|
|
526
|
-
overflow-y: hidden;
|
|
527
|
-
padding: var(--spacing-vsp-xs) 0;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
.katex-display > .katex {
|
|
531
|
-
white-space: nowrap;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/* Make KaTeX respect our color scheme */
|
|
535
|
-
.katex .base {
|
|
536
|
-
color: var(--zd-fg);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
316
|
/* ── Search highlight ── */
|
|
540
317
|
[data-search-results] mark {
|
|
541
318
|
background-color: var(--color-matched-keyword-bg);
|
|
@@ -544,30 +321,6 @@ pre[class^="syntect-"] .line .highlighted-word {
|
|
|
544
321
|
border-radius: 2px;
|
|
545
322
|
}
|
|
546
323
|
|
|
547
|
-
/* ========================================
|
|
548
|
-
* Page transition animations
|
|
549
|
-
* ======================================== */
|
|
550
|
-
|
|
551
|
-
@keyframes contentFadeIn {
|
|
552
|
-
from {
|
|
553
|
-
opacity: 0;
|
|
554
|
-
transform: translateY(-0.75rem);
|
|
555
|
-
}
|
|
556
|
-
to {
|
|
557
|
-
opacity: 1;
|
|
558
|
-
transform: translateY(0);
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
@keyframes contentFadeOut {
|
|
563
|
-
from {
|
|
564
|
-
opacity: 1;
|
|
565
|
-
}
|
|
566
|
-
to {
|
|
567
|
-
opacity: 0;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
324
|
/* Version-switcher responsive visibility (moved out of the component to
|
|
572
325
|
* avoid <style>-inside-<div> HTML5 content-model violation; required when
|
|
573
326
|
* the i18nVersion feature ships a <VersionSwitcher> wrapped in
|
|
@@ -579,61 +332,6 @@ pre[class^="syntect-"] .line .highlighted-word {
|
|
|
579
332
|
}
|
|
580
333
|
}
|
|
581
334
|
|
|
582
|
-
/* ========================================
|
|
583
|
-
* Desktop sidebar toggle (W7A: unconditional — feature gates at runtime)
|
|
584
|
-
* ======================================== */
|
|
585
|
-
|
|
586
|
-
@media (min-width: 1024px) {
|
|
587
|
-
#desktop-sidebar {
|
|
588
|
-
transition:
|
|
589
|
-
transform var(--zd-transition-slow) ease-in-out,
|
|
590
|
-
visibility var(--zd-transition-slow);
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
html[data-sidebar-hidden] #desktop-sidebar {
|
|
594
|
-
transform: translateX(calc(-1 * var(--zd-sidebar-w)));
|
|
595
|
-
visibility: hidden;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
.zd-sidebar-content-wrapper {
|
|
599
|
-
transition: margin-left var(--zd-transition-slow) ease-in-out;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
html[data-sidebar-hidden] .zd-sidebar-content-wrapper {
|
|
603
|
-
margin-left: 0;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
/* When hidden via the toggle, narrow the content band to the
|
|
607
|
-
* hide_sidebar frontmatter width so it centers (the flex parent already
|
|
608
|
-
* applies justify-content: center) instead of leaving a dead gap where
|
|
609
|
-
* the sidebar was. 80rem must match the `max-w-[80rem]` hide_sidebar
|
|
610
|
-
* branch in doc-layout.tsx. These rules are unlayered, so they win over
|
|
611
|
-
* the Tailwind `max-w-[clamp(...)]` utility (utilities layer). (#2002) */
|
|
612
|
-
.zd-doc-content-band {
|
|
613
|
-
transition: max-width var(--zd-transition-slow) ease-in-out;
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
html[data-sidebar-hidden] .zd-doc-content-band {
|
|
617
|
-
max-width: 80rem;
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
/* Sidebar toggle button — left position uses CSS variable, needs global rule */
|
|
622
|
-
@media (min-width: 1024px) {
|
|
623
|
-
.zd-desktop-sidebar-toggle {
|
|
624
|
-
left: var(--zd-sidebar-w);
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
html[data-sidebar-hidden] .zd-desktop-sidebar-toggle {
|
|
628
|
-
left: 0;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
/* The SPA-swap flash guard (`data-sidebar-no-transition`) was removed once
|
|
633
|
-
* doc-layout adopted <ClientRouter preserveHtmlAttrs={["data-sidebar-hidden",
|
|
634
|
-
* ...]} /> (zfb-runtime >= 0.1.0-next.52): the attribute now survives the swap
|
|
635
|
-
* before paint, so no sidebar geometry transition fires mid-swap. */
|
|
636
|
-
|
|
637
335
|
/* ── Find-in-page highlight (W7A: unconditional — Tauri feature gates at runtime) ── */
|
|
638
336
|
.find-match {
|
|
639
337
|
background-color: color-mix(in oklch, var(--color-warning) 40%, transparent);
|
|
@@ -645,276 +343,4 @@ pre[class^="syntect-"] .line .highlighted-word {
|
|
|
645
343
|
outline: 2px solid color-mix(in oklch, var(--color-warning) 90%, transparent);
|
|
646
344
|
}
|
|
647
345
|
|
|
648
|
-
/* ========================================
|
|
649
|
-
* Image enlarge (.zd-enlargeable) — W7A: unconditional, runtime-gated
|
|
650
|
-
* ======================================== */
|
|
651
|
-
|
|
652
|
-
.zd-enlargeable {
|
|
653
|
-
position: relative;
|
|
654
|
-
display: block;
|
|
655
|
-
margin-inline: 0;
|
|
656
|
-
margin-block-end: 0;
|
|
657
|
-
border: 1px solid transparent;
|
|
658
|
-
transition: border-color var(--default-transition-duration);
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
/* Eligible images (expand-btn visible): the entire image becomes the click target.
|
|
662
|
-
* Show a subtle border as the interactivity affordance, accent on hover. */
|
|
663
|
-
.zd-enlargeable:has(.zd-enlarge-btn:not([hidden])) {
|
|
664
|
-
border-color: var(--color-muted);
|
|
665
|
-
cursor: pointer;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
.zd-enlargeable:has(.zd-enlarge-btn:not([hidden])):hover {
|
|
669
|
-
border-color: var(--color-accent);
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
.zd-enlargeable img {
|
|
673
|
-
display: block;
|
|
674
|
-
max-width: 100%;
|
|
675
|
-
height: auto;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
.zd-enlarge-btn {
|
|
679
|
-
position: absolute;
|
|
680
|
-
top: var(--spacing-image-overlay-inset);
|
|
681
|
-
right: var(--spacing-image-overlay-inset);
|
|
682
|
-
display: flex;
|
|
683
|
-
align-items: center;
|
|
684
|
-
justify-content: center;
|
|
685
|
-
padding: var(--spacing-image-overlay-inset);
|
|
686
|
-
border: none;
|
|
687
|
-
background: transparent;
|
|
688
|
-
cursor: pointer;
|
|
689
|
-
z-index: var(--z-index-local-1);
|
|
690
|
-
transition: opacity var(--default-transition-duration);
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
.zd-enlarge-btn::before {
|
|
694
|
-
content: "";
|
|
695
|
-
position: absolute;
|
|
696
|
-
inset: 0;
|
|
697
|
-
background: color-mix(in oklch, var(--color-image-overlay-bg) 80%, transparent);
|
|
698
|
-
z-index: var(--z-index-local-1);
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
.zd-enlarge-btn > svg {
|
|
702
|
-
position: relative;
|
|
703
|
-
z-index: var(--z-index-local-2);
|
|
704
|
-
width: var(--spacing-icon-sm);
|
|
705
|
-
height: var(--spacing-icon-sm);
|
|
706
|
-
color: var(--color-image-overlay-fg);
|
|
707
|
-
fill: currentColor;
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
.zd-enlarge-btn:hover {
|
|
711
|
-
opacity: 0.8;
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
.zd-enlarge-btn[hidden] {
|
|
715
|
-
display: none !important;
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
dialog.zd-enlarge-dialog::backdrop {
|
|
719
|
-
background: color-mix(in oklch, var(--color-overlay) 80%, transparent);
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
/* Close button is positioned to the VIEWPORT corner (not the dialog) so it
|
|
723
|
-
* stays visually distinct against any image, regardless of the dialog's size.
|
|
724
|
-
* This relies on the dialog being transform-free (see DIALOG_STYLE in
|
|
725
|
-
* image-enlarge.tsx) — a transform on the dialog would re-anchor this fixed
|
|
726
|
-
* button to the dialog corner. */
|
|
727
|
-
.zd-enlarge-dialog-close {
|
|
728
|
-
position: fixed;
|
|
729
|
-
top: 4px;
|
|
730
|
-
right: 4px;
|
|
731
|
-
display: flex;
|
|
732
|
-
align-items: center;
|
|
733
|
-
justify-content: center;
|
|
734
|
-
padding: var(--spacing-image-overlay-inset);
|
|
735
|
-
border: none;
|
|
736
|
-
background: transparent;
|
|
737
|
-
cursor: pointer;
|
|
738
|
-
z-index: var(--z-index-local-1);
|
|
739
|
-
transition: opacity var(--default-transition-duration);
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
.zd-enlarge-dialog-close:hover {
|
|
743
|
-
opacity: 0.8;
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
.zd-enlarge-dialog-close::before {
|
|
747
|
-
content: "";
|
|
748
|
-
position: absolute;
|
|
749
|
-
inset: 0;
|
|
750
|
-
background: color-mix(in oklch, var(--color-image-overlay-bg) 80%, transparent);
|
|
751
|
-
z-index: var(--z-index-local-1);
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
.zd-enlarge-dialog-close > svg {
|
|
755
|
-
position: relative;
|
|
756
|
-
z-index: var(--z-index-local-2);
|
|
757
|
-
width: var(--spacing-icon-lg);
|
|
758
|
-
height: var(--spacing-icon-lg);
|
|
759
|
-
color: var(--color-image-overlay-fg);
|
|
760
|
-
fill: currentColor;
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
/* Wide viewport: ~2× larger close button to read clearly against any image. */
|
|
764
|
-
@media (min-width: 1024px) {
|
|
765
|
-
.zd-enlarge-dialog-close {
|
|
766
|
-
top: 10px;
|
|
767
|
-
right: 10px;
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
.zd-enlarge-dialog-close > svg {
|
|
771
|
-
width: calc(var(--spacing-icon-lg) * 2);
|
|
772
|
-
height: calc(var(--spacing-icon-lg) * 2);
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
/* ========================================
|
|
777
|
-
* Mermaid enlarge (.zd-mermaid-enlargeable) — issue #2176 / #2178
|
|
778
|
-
*
|
|
779
|
-
* Unlike images (SSR-wrapped in figure.zd-enlargeable), mermaid diagrams render
|
|
780
|
-
* client-side, so the mermaid-enlarge island injects the `.zd-enlarge-btn` into
|
|
781
|
-
* each rendered `.mermaid` container and adds `.zd-mermaid-enlargeable` (which
|
|
782
|
-
* makes the container position:relative so the button anchors to it). The
|
|
783
|
-
* button + close-button visuals are SHARED with image-enlarge above
|
|
784
|
-
* (`.zd-enlarge-btn`, `.zd-enlarge-dialog-close`).
|
|
785
|
-
* ======================================== */
|
|
786
|
-
|
|
787
|
-
.zd-mermaid-enlargeable {
|
|
788
|
-
position: relative;
|
|
789
|
-
border: 1px solid transparent;
|
|
790
|
-
border-radius: var(--radius-DEFAULT);
|
|
791
|
-
transition: border-color var(--default-transition-duration);
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
/* The diagram is always enlargeable once the button is injected — show a subtle
|
|
795
|
-
* border affordance, accent on hover (mirrors the image-enlarge affordance). */
|
|
796
|
-
.zd-mermaid-enlargeable:has(.zd-enlarge-btn) {
|
|
797
|
-
cursor: pointer;
|
|
798
|
-
border-color: var(--color-muted);
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
.zd-mermaid-enlargeable:has(.zd-enlarge-btn):hover {
|
|
802
|
-
border-color: var(--color-accent);
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
/* Zoom/pan dialog. The `<dialog>` stays transform-free (see DIALOG_STYLE in
|
|
806
|
-
* mermaid-enlarge.tsx); the transform lives on .zd-mermaid-transform. */
|
|
807
|
-
dialog.zd-mermaid-dialog::backdrop {
|
|
808
|
-
background: color-mix(in oklch, var(--color-overlay) 80%, transparent);
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
/* Pan viewport — fills the dialog and clips the (possibly zoomed) diagram.
|
|
812
|
-
* touch-action:none so pointer-drag pans on touch without the browser
|
|
813
|
-
* intercepting the gesture for scrolling. */
|
|
814
|
-
.zd-mermaid-viewport {
|
|
815
|
-
width: 100%;
|
|
816
|
-
height: 100%;
|
|
817
|
-
overflow: hidden;
|
|
818
|
-
display: flex;
|
|
819
|
-
align-items: center;
|
|
820
|
-
justify-content: center;
|
|
821
|
-
touch-action: none;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
.zd-mermaid-viewport[data-pan-active] {
|
|
825
|
-
cursor: grab;
|
|
826
|
-
/* In pan mode a drag should pan, not select diagram text. Scoped to
|
|
827
|
-
* [data-pan-active] so text stays selectable when pan mode is off. */
|
|
828
|
-
-webkit-user-select: none;
|
|
829
|
-
user-select: none;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
.zd-mermaid-viewport[data-pan-active]:active {
|
|
833
|
-
cursor: grabbing;
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
.zd-mermaid-transform {
|
|
837
|
-
width: 100%;
|
|
838
|
-
height: 100%;
|
|
839
|
-
display: flex;
|
|
840
|
-
align-items: center;
|
|
841
|
-
justify-content: center;
|
|
842
|
-
will-change: transform;
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
/* SVG sizing — fit the cloned mermaid svg inside the dialog like
|
|
846
|
-
* object-fit:contain. The svg fills the viewport box (100% x 100%) and its
|
|
847
|
-
* viewBox content is letterboxed/centered by the default
|
|
848
|
-
* preserveAspectRatio="xMidYMid meet". A TALL diagram (e.g. a state diagram) no
|
|
849
|
-
* longer gets forced to full dialog width with `height:auto` driving the height
|
|
850
|
-
* far past the viewport via its aspect ratio — it now shrinks to fit the height
|
|
851
|
-
* instead. max-width/max-height !important neutralize the inline px sizing
|
|
852
|
-
* mermaid bakes onto the svg (without it the diagram renders tiny). Scoped to
|
|
853
|
-
* .zd-mermaid-transform (the cloned-diagram wrapper) so it does NOT hit the
|
|
854
|
-
* toolbar / close-button icon svgs that also live inside the dialog. */
|
|
855
|
-
.zd-mermaid-transform svg {
|
|
856
|
-
max-width: 100% !important;
|
|
857
|
-
max-height: 100% !important;
|
|
858
|
-
width: 100%;
|
|
859
|
-
height: 100%;
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
/* Edge labels (e.g. "Yes"/"No") render inside a tightly-sized <foreignObject>;
|
|
863
|
-
* when the cloned diagram is upscaled to fill the dialog, sub-pixel overflow
|
|
864
|
-
* makes the browser clip the last glyph at the foreignObject's right edge.
|
|
865
|
-
* Letting the foreignObject overflow render keeps the full label visible. */
|
|
866
|
-
.zd-mermaid-transform svg foreignObject {
|
|
867
|
-
overflow: visible;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
/* Toolbar — bottom-right pill of zoom/pan controls (2× sized buttons). */
|
|
871
|
-
.zd-mermaid-toolbar {
|
|
872
|
-
position: absolute;
|
|
873
|
-
bottom: var(--spacing-image-overlay-inset);
|
|
874
|
-
right: var(--spacing-image-overlay-inset);
|
|
875
|
-
display: flex;
|
|
876
|
-
gap: var(--spacing-hsp-xs);
|
|
877
|
-
padding: var(--spacing-hsp-xs);
|
|
878
|
-
border: 1px solid var(--color-muted);
|
|
879
|
-
border-radius: var(--radius-DEFAULT);
|
|
880
|
-
background: color-mix(in oklch, var(--color-surface) 92%, transparent);
|
|
881
|
-
z-index: var(--z-index-local-2);
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
.zd-mermaid-tool-btn {
|
|
885
|
-
display: flex;
|
|
886
|
-
align-items: center;
|
|
887
|
-
justify-content: center;
|
|
888
|
-
width: calc(var(--spacing-icon-lg) * 2);
|
|
889
|
-
height: calc(var(--spacing-icon-lg) * 2);
|
|
890
|
-
padding: var(--spacing-vsp-2xs);
|
|
891
|
-
border: none;
|
|
892
|
-
border-radius: var(--radius-DEFAULT);
|
|
893
|
-
background: transparent;
|
|
894
|
-
color: var(--color-fg);
|
|
895
|
-
cursor: pointer;
|
|
896
|
-
transition:
|
|
897
|
-
background-color var(--default-transition-duration),
|
|
898
|
-
opacity var(--default-transition-duration);
|
|
899
|
-
}
|
|
900
|
-
|
|
901
|
-
.zd-mermaid-tool-btn:hover:not([disabled]) {
|
|
902
|
-
background: color-mix(in oklch, var(--color-muted) 25%, transparent);
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
.zd-mermaid-tool-btn[aria-pressed="true"] {
|
|
906
|
-
background: color-mix(in oklch, var(--color-accent) 30%, transparent);
|
|
907
|
-
color: var(--color-accent);
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
.zd-mermaid-tool-btn[disabled] {
|
|
911
|
-
opacity: 0.4;
|
|
912
|
-
cursor: default;
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
.zd-mermaid-tool-btn > svg {
|
|
916
|
-
width: calc(var(--spacing-icon-md) * 2);
|
|
917
|
-
height: calc(var(--spacing-icon-md) * 2);
|
|
918
|
-
}
|
|
919
|
-
|
|
920
346
|
/* @slot:global-css:feature-styles */
|
|
@@ -156,7 +156,7 @@ export function isDefaultLocaleOnlyPath(path: string): boolean {
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
/** Build a versioned docs URL for the given slug, version, and lang. */
|
|
159
|
-
export function versionedDocsUrl(slug: string, versionSlug: string, lang: Locale = defaultLocale): string {
|
|
159
|
+
export function versionedDocsUrl(slug: string, versionSlug: string, lang: Locale | string = defaultLocale): string {
|
|
160
160
|
const path = lang === defaultLocale
|
|
161
161
|
? `/v/${versionSlug}/docs/${slug}`
|
|
162
162
|
: `/v/${versionSlug}/${lang}/docs/${slug}`;
|