@rspress-theme-anatole/theme-default 0.7.22 → 0.7.23
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/bundle.js +447 -176
- package/package.json +4 -4
package/dist/bundle.js
CHANGED
|
@@ -334,21 +334,223 @@ function useLocaleSiteData() {
|
|
|
334
334
|
langRoutePrefix: lang === defaultLang ? '/' : (0, __WEBPACK_EXTERNAL_MODULE__rspress_shared_baa012d0__.addTrailingSlash)(lang)
|
|
335
335
|
};
|
|
336
336
|
}
|
|
337
|
+
function normalizeRoleList(value) {
|
|
338
|
+
if (!value) return [];
|
|
339
|
+
const list = Array.isArray(value) ? value : String(value).split(',');
|
|
340
|
+
return list.map((role) => String(role).trim().toLowerCase()).filter(Boolean);
|
|
341
|
+
}
|
|
342
|
+
// Cache for user roles fetched from userContext endpoint
|
|
343
|
+
let _cachedUserRoles = null;
|
|
344
|
+
let _userRolesFetchPromise = null;
|
|
345
|
+
|
|
346
|
+
function getUserRoles() {
|
|
347
|
+
// Return cached roles if available
|
|
348
|
+
if (_cachedUserRoles !== null) return _cachedUserRoles;
|
|
349
|
+
return [];
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async function fetchUserRoles(userContextUrl) {
|
|
353
|
+
if (!userContextUrl) return [];
|
|
354
|
+
if (_cachedUserRoles !== null) return _cachedUserRoles;
|
|
355
|
+
if (_userRolesFetchPromise) return _userRolesFetchPromise;
|
|
356
|
+
|
|
357
|
+
_userRolesFetchPromise = (async () => {
|
|
358
|
+
try {
|
|
359
|
+
const response = await fetch(userContextUrl, { credentials: 'include' });
|
|
360
|
+
if (!response.ok) {
|
|
361
|
+
console.warn('Failed to fetch user context:', response.status);
|
|
362
|
+
_cachedUserRoles = [];
|
|
363
|
+
return [];
|
|
364
|
+
}
|
|
365
|
+
const data = await response.json();
|
|
366
|
+
const roles = data?.permissions?.roles || [];
|
|
367
|
+
_cachedUserRoles = normalizeRoleList(roles);
|
|
368
|
+
// Dispatch event to trigger sidebar re-render
|
|
369
|
+
if (typeof window !== 'undefined') {
|
|
370
|
+
window.dispatchEvent(new Event('UserRolesReady'));
|
|
371
|
+
}
|
|
372
|
+
return _cachedUserRoles;
|
|
373
|
+
} catch (e) {
|
|
374
|
+
console.warn('Error fetching user context:', e);
|
|
375
|
+
_cachedUserRoles = [];
|
|
376
|
+
return [];
|
|
377
|
+
} finally {
|
|
378
|
+
_userRolesFetchPromise = null;
|
|
379
|
+
}
|
|
380
|
+
})();
|
|
381
|
+
|
|
382
|
+
return _userRolesFetchPromise;
|
|
383
|
+
}
|
|
384
|
+
function isItemLocked(item, userRoles) {
|
|
385
|
+
const requiredRoles = normalizeRoleList(item?.roles);
|
|
386
|
+
// No roles required = public content (not locked)
|
|
387
|
+
if (!requiredRoles.length) return false;
|
|
388
|
+
// Has roles required but user has matching role = unlocked
|
|
389
|
+
if (userRoles.length && requiredRoles.some((role) => userRoles.includes(role))) return false;
|
|
390
|
+
// Has roles required but user doesn't have matching role = locked
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
function markLockedSidebarItems(items, userRoles) {
|
|
394
|
+
if (!Array.isArray(items)) return items;
|
|
395
|
+
return items.map((item) => {
|
|
396
|
+
if (!item) return null;
|
|
397
|
+
let nextItem = item;
|
|
398
|
+
const locked = isItemLocked(item, userRoles);
|
|
399
|
+
if (locked) {
|
|
400
|
+
nextItem = { ...nextItem, locked: true };
|
|
401
|
+
}
|
|
402
|
+
if ('items' in item && Array.isArray(item.items)) {
|
|
403
|
+
const markedItems = markLockedSidebarItems(item.items, userRoles);
|
|
404
|
+
nextItem = { ...nextItem, items: markedItems };
|
|
405
|
+
}
|
|
406
|
+
return nextItem;
|
|
407
|
+
}).filter(Boolean);
|
|
408
|
+
}
|
|
337
409
|
function useSidebarData() {
|
|
338
410
|
const { sidebar } = useLocaleSiteData();
|
|
411
|
+
const { siteData } = (0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.usePageData)();
|
|
339
412
|
const { pathname: rawPathname } = (0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.useLocation)();
|
|
340
413
|
const pathname = decodeURIComponent(rawPathname);
|
|
341
|
-
const
|
|
414
|
+
const [roleVersion, setRoleVersion] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(0);
|
|
415
|
+
|
|
416
|
+
// Fetch user roles from userContext endpoint
|
|
417
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(() => {
|
|
418
|
+
const userContextUrl = siteData?.auth?.endpoints?.userContext;
|
|
419
|
+
if (userContextUrl) {
|
|
420
|
+
fetchUserRoles(userContextUrl);
|
|
421
|
+
}
|
|
422
|
+
}, [siteData?.auth?.endpoints?.userContext]);
|
|
423
|
+
|
|
424
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(() => {
|
|
425
|
+
if ('undefined' == typeof window) return;
|
|
426
|
+
const handler = () => setRoleVersion((v) => v + 1);
|
|
427
|
+
window.addEventListener('MetaRolesReady', handler);
|
|
428
|
+
window.addEventListener('UserRolesReady', handler);
|
|
429
|
+
return () => {
|
|
430
|
+
window.removeEventListener('MetaRolesReady', handler);
|
|
431
|
+
window.removeEventListener('UserRolesReady', handler);
|
|
432
|
+
};
|
|
433
|
+
}, []);
|
|
434
|
+
const sidebarData = (0, __WEBPACK_EXTERNAL_MODULE_react__.useMemo)(() => {
|
|
435
|
+
const data = getSidebarDataGroup(sidebar, pathname);
|
|
436
|
+
const userRoles = getUserRoles();
|
|
437
|
+
let dataWithRoles = data;
|
|
438
|
+
try {
|
|
439
|
+
const roleMap = 'undefined' != typeof window ? window.__META_ROLE_MAP__ : null;
|
|
440
|
+
if (roleMap) {
|
|
441
|
+
const applyRoles = (items) => {
|
|
442
|
+
if (!Array.isArray(items)) return items;
|
|
443
|
+
return items.map((item) => {
|
|
444
|
+
if (!item) return item;
|
|
445
|
+
let nextItem = item;
|
|
446
|
+
const key = item._fileKey;
|
|
447
|
+
if (key && roleMap[key]) {
|
|
448
|
+
nextItem = {
|
|
449
|
+
...nextItem,
|
|
450
|
+
roles: roleMap[key]
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
if ('items' in nextItem && Array.isArray(nextItem.items)) {
|
|
454
|
+
const nextItems = applyRoles(nextItem.items);
|
|
455
|
+
if (nextItems !== nextItem.items) {
|
|
456
|
+
nextItem = {
|
|
457
|
+
...nextItem,
|
|
458
|
+
items: nextItems
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return nextItem;
|
|
463
|
+
});
|
|
464
|
+
};
|
|
465
|
+
dataWithRoles = applyRoles(data);
|
|
466
|
+
}
|
|
467
|
+
} catch (e) {
|
|
468
|
+
}
|
|
469
|
+
return markLockedSidebarItems(dataWithRoles, userRoles);
|
|
470
|
+
}, [
|
|
342
471
|
sidebar,
|
|
343
|
-
pathname
|
|
472
|
+
pathname,
|
|
473
|
+
roleVersion
|
|
344
474
|
]);
|
|
345
475
|
return sidebarData;
|
|
346
476
|
}
|
|
477
|
+
|
|
478
|
+
// Get first accessible (not locked) page from sidebar items
|
|
479
|
+
function getFirstAccessiblePage(items) {
|
|
480
|
+
if (!Array.isArray(items)) return null;
|
|
481
|
+
|
|
482
|
+
for (const item of items) {
|
|
483
|
+
if (!item) continue;
|
|
484
|
+
if ('dividerType' in item) continue;
|
|
485
|
+
|
|
486
|
+
// If item is locked, skip it
|
|
487
|
+
if (item.locked === true) continue;
|
|
488
|
+
|
|
489
|
+
// If item has a link and is not locked, return it
|
|
490
|
+
if ('link' in item && item.link) {
|
|
491
|
+
return { text: item.text, link: item.link };
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// If item has children, search recursively
|
|
495
|
+
if ('items' in item && Array.isArray(item.items)) {
|
|
496
|
+
const found = getFirstAccessiblePage(item.items);
|
|
497
|
+
if (found) return found;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Hook to redirect to first accessible page if current page is locked
|
|
505
|
+
function useRedirectToAccessiblePage() {
|
|
506
|
+
const { pathname } = (0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.useLocation)();
|
|
507
|
+
const navigate = (0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.useNavigate)();
|
|
508
|
+
const items = useSidebarData();
|
|
509
|
+
|
|
510
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(() => {
|
|
511
|
+
if (!items || items.length === 0) return;
|
|
512
|
+
|
|
513
|
+
// Find current page in sidebar
|
|
514
|
+
const findCurrentPage = (items, targetPath) => {
|
|
515
|
+
for (const item of items) {
|
|
516
|
+
if (!item) continue;
|
|
517
|
+
if ('dividerType' in item) continue;
|
|
518
|
+
|
|
519
|
+
if ('link' in item && item.link) {
|
|
520
|
+
const itemPath = (0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.withBase)(item.link);
|
|
521
|
+
if ((0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.isEqualPath)(itemPath, targetPath)) {
|
|
522
|
+
return item;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if ('items' in item && Array.isArray(item.items)) {
|
|
527
|
+
const found = findCurrentPage(item.items, targetPath);
|
|
528
|
+
if (found) return found;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return null;
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
const currentPage = findCurrentPage(items, pathname);
|
|
535
|
+
|
|
536
|
+
// If current page is locked, redirect to first accessible page
|
|
537
|
+
if (currentPage && currentPage.locked === true) {
|
|
538
|
+
const firstAccessible = getFirstAccessiblePage(items);
|
|
539
|
+
if (firstAccessible && firstAccessible.link) {
|
|
540
|
+
navigate((0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.withBase)(firstAccessible.link), { replace: true });
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}, [items, pathname, navigate]);
|
|
544
|
+
}
|
|
545
|
+
|
|
347
546
|
function usePrevNextPage() {
|
|
348
547
|
const { pathname } = (0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.useLocation)();
|
|
349
548
|
const items = useSidebarData();
|
|
350
549
|
const flattenTitles = [];
|
|
351
550
|
const walk = (sidebarItem) => {
|
|
551
|
+
// Skip locked items
|
|
552
|
+
if (sidebarItem.locked === true) return;
|
|
553
|
+
|
|
352
554
|
if ('items' in sidebarItem) {
|
|
353
555
|
if (sidebarItem.link) flattenTitles.push({
|
|
354
556
|
text: sidebarItem.text,
|
|
@@ -553,9 +755,29 @@ function SidebarGroup(props) {
|
|
|
553
755
|
const initialState = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)('collapsed' in item && item.collapsed);
|
|
554
756
|
const active = item.link && activeMatcher(item.link);
|
|
555
757
|
const { collapsed, collapsible = true } = item;
|
|
758
|
+
const isLocked = item.locked === true;
|
|
759
|
+
|
|
760
|
+
// Lock icon SVG for groups
|
|
761
|
+
const GroupLockIcon = () => (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("svg", {
|
|
762
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
763
|
+
width: "14",
|
|
764
|
+
height: "14",
|
|
765
|
+
viewBox: "0 0 24 24",
|
|
766
|
+
fill: "none",
|
|
767
|
+
stroke: "currentColor",
|
|
768
|
+
strokeWidth: "2",
|
|
769
|
+
strokeLinecap: "round",
|
|
770
|
+
strokeLinejoin: "round",
|
|
771
|
+
style: { marginLeft: '6px', opacity: 0.6, flexShrink: 0 },
|
|
772
|
+
children: [
|
|
773
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
|
|
774
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
|
|
775
|
+
]
|
|
776
|
+
});
|
|
777
|
+
|
|
556
778
|
const collapsibleIcon = (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("div", {
|
|
557
779
|
style: {
|
|
558
|
-
cursor: 'pointer',
|
|
780
|
+
cursor: isLocked ? 'not-allowed' : 'pointer',
|
|
559
781
|
transition: 'transform 0.2s ease-out',
|
|
560
782
|
transform: collapsed ? 'rotate(0deg)' : 'rotate(90deg)'
|
|
561
783
|
},
|
|
@@ -593,6 +815,7 @@ function SidebarGroup(props) {
|
|
|
593
815
|
}, []);
|
|
594
816
|
const toggleCollapse = (e) => {
|
|
595
817
|
e.stopPropagation();
|
|
818
|
+
if (isLocked) return; // Prevent collapse toggle for locked items
|
|
596
819
|
setSidebarData((sidebarData) => {
|
|
597
820
|
const newSidebarData = [
|
|
598
821
|
...sidebarData
|
|
@@ -610,23 +833,29 @@ function SidebarGroup(props) {
|
|
|
610
833
|
className: "rspress-sidebar-section mt-0.5 block",
|
|
611
834
|
"data-context": item.context,
|
|
612
835
|
style: {
|
|
613
|
-
marginLeft: 0 === depth ? 0 : '18px'
|
|
836
|
+
marginLeft: 0 === depth ? 0 : '18px',
|
|
837
|
+
opacity: isLocked ? 0.6 : 1
|
|
614
838
|
},
|
|
615
839
|
children: [
|
|
616
840
|
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsxs)("div", {
|
|
617
841
|
className: `rspress-sidebar-collapse flex items-center ${active ? Sidebar_index_module.menuItemActive : Sidebar_index_module.menuItem}`,
|
|
618
842
|
"data-context": item.context,
|
|
619
|
-
onMouseEnter: () => item.link && preloadLink(item.link),
|
|
843
|
+
onMouseEnter: () => !isLocked && item.link && preloadLink(item.link),
|
|
620
844
|
onClick: (e) => {
|
|
845
|
+
if (isLocked) {
|
|
846
|
+
e.preventDefault();
|
|
847
|
+
e.stopPropagation();
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
621
850
|
if (item.link) navigate((0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.withBase)((0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.normalizeHrefInRuntime)(item.link)));
|
|
622
851
|
collapsible && toggleCollapse(e);
|
|
623
852
|
},
|
|
624
853
|
style: {
|
|
625
854
|
// borderRadius: 0 === depth ? '0 var(--rp-radius) var(--rp-radius) 0' : void 0,
|
|
626
|
-
cursor: collapsible || item.link ? 'pointer' : 'normal'
|
|
855
|
+
cursor: isLocked ? 'not-allowed' : (collapsible || item.link ? 'pointer' : 'normal')
|
|
627
856
|
},
|
|
628
857
|
children: [
|
|
629
|
-
collapsible && (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("div", {
|
|
858
|
+
collapsible && !isLocked && (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("div", {
|
|
630
859
|
className: `${Sidebar_index_module.collapseContainer} p-2 rounded-xl`,
|
|
631
860
|
style: {
|
|
632
861
|
paddingRight: 0
|
|
@@ -635,7 +864,7 @@ function SidebarGroup(props) {
|
|
|
635
864
|
children: collapsibleIcon
|
|
636
865
|
}),
|
|
637
866
|
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsxs)("h2", {
|
|
638
|
-
className: "py-2 px-2 text-sm font-medium flex",
|
|
867
|
+
className: "py-2 px-2 text-sm font-medium flex items-center",
|
|
639
868
|
style: {
|
|
640
869
|
...highlightTitleStyle
|
|
641
870
|
},
|
|
@@ -651,12 +880,13 @@ function SidebarGroup(props) {
|
|
|
651
880
|
letterSpacing: '-1%'
|
|
652
881
|
},
|
|
653
882
|
children: renderInlineMarkdown(item.text)
|
|
654
|
-
})
|
|
883
|
+
}),
|
|
884
|
+
isLocked && (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(GroupLockIcon, {})
|
|
655
885
|
]
|
|
656
886
|
})
|
|
657
887
|
]
|
|
658
888
|
}),
|
|
659
|
-
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("div", {
|
|
889
|
+
!isLocked && (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("div", {
|
|
660
890
|
ref: containerRef,
|
|
661
891
|
className: "transition-all duration-300 ease-in-out",
|
|
662
892
|
style: {
|
|
@@ -692,6 +922,7 @@ function SidebarItem(props) {
|
|
|
692
922
|
const { item, depth = 0, activeMatcher, id, setSidebarData } = props;
|
|
693
923
|
const active = 'link' in item && item.link && activeMatcher(item.link);
|
|
694
924
|
const ref = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(null);
|
|
925
|
+
const isLocked = item.locked === true;
|
|
695
926
|
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(() => {
|
|
696
927
|
if (active) ref.current?.scrollIntoView({
|
|
697
928
|
block: 'center'
|
|
@@ -705,6 +936,65 @@ function SidebarItem(props) {
|
|
|
705
936
|
collapsed: item.collapsed,
|
|
706
937
|
setSidebarData: setSidebarData
|
|
707
938
|
}, `${item.text}-${id}`);
|
|
939
|
+
|
|
940
|
+
// Lock icon SVG
|
|
941
|
+
const LockIcon = () => (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("svg", {
|
|
942
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
943
|
+
width: "14",
|
|
944
|
+
height: "14",
|
|
945
|
+
viewBox: "0 0 24 24",
|
|
946
|
+
fill: "none",
|
|
947
|
+
stroke: "currentColor",
|
|
948
|
+
strokeWidth: "2",
|
|
949
|
+
strokeLinecap: "round",
|
|
950
|
+
strokeLinejoin: "round",
|
|
951
|
+
style: { marginLeft: '6px', opacity: 0.6, flexShrink: 0 },
|
|
952
|
+
children: [
|
|
953
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }),
|
|
954
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
|
|
955
|
+
]
|
|
956
|
+
});
|
|
957
|
+
|
|
958
|
+
if (isLocked) {
|
|
959
|
+
// Locked item - show lock icon and prevent navigation
|
|
960
|
+
return (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("div", {
|
|
961
|
+
className: Sidebar_index_module.menuLink,
|
|
962
|
+
onClick: (e) => {
|
|
963
|
+
e.preventDefault();
|
|
964
|
+
e.stopPropagation();
|
|
965
|
+
},
|
|
966
|
+
style: { cursor: 'not-allowed' },
|
|
967
|
+
children: (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsxs)("div", {
|
|
968
|
+
ref: ref,
|
|
969
|
+
className: `${Sidebar_index_module.menuItem} mt-0.5 py-2 px-3 font-medium flex items-center justify-between`,
|
|
970
|
+
style: {
|
|
971
|
+
fontSize: 0 === depth ? '14px' : '13px',
|
|
972
|
+
marginLeft: 0 === depth ? 0 : '18px',
|
|
973
|
+
opacity: 0.6,
|
|
974
|
+
...0 === depth ? highlightTitleStyle : {}
|
|
975
|
+
},
|
|
976
|
+
children: [
|
|
977
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsxs)("span", {
|
|
978
|
+
className: "flex items-center",
|
|
979
|
+
children: [
|
|
980
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(__WEBPACK_EXTERNAL_MODULE__theme_75e53063__.Tag, {
|
|
981
|
+
tag: item.tag
|
|
982
|
+
}),
|
|
983
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("span", {
|
|
984
|
+
style: {
|
|
985
|
+
fontSize: 0 === depth ? '14px' : '13px',
|
|
986
|
+
fontWeight: 400
|
|
987
|
+
},
|
|
988
|
+
children: renderInlineMarkdown(item.text)
|
|
989
|
+
})
|
|
990
|
+
]
|
|
991
|
+
}),
|
|
992
|
+
(0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(LockIcon, {})
|
|
993
|
+
]
|
|
994
|
+
})
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
|
|
708
998
|
return (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)(__WEBPACK_EXTERNAL_MODULE__theme_75e53063__.Link, {
|
|
709
999
|
href: (0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.normalizeHrefInRuntime)(item.link),
|
|
710
1000
|
className: Sidebar_index_module.menuLink,
|
|
@@ -1659,6 +1949,7 @@ const Layout = (props) => {
|
|
|
1659
1949
|
const { pageType, lang: currentLang, title: articleTitle, frontmatter = {} } = page;
|
|
1660
1950
|
const localesData = useLocaleSiteData();
|
|
1661
1951
|
useRedirect4FirstVisit();
|
|
1952
|
+
useRedirectToAccessiblePage();
|
|
1662
1953
|
let title = frontmatter.title ?? articleTitle;
|
|
1663
1954
|
const mainTitle = siteData.title || localesData.title || '';
|
|
1664
1955
|
title = title &&
|
|
@@ -4581,11 +4872,6 @@ function NavVersions() {
|
|
|
4581
4872
|
});
|
|
4582
4873
|
}
|
|
4583
4874
|
// Utility functions for cookie management
|
|
4584
|
-
function setCookie(name, value, days = 7) {
|
|
4585
|
-
const expires = new Date();
|
|
4586
|
-
expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000));
|
|
4587
|
-
document.cookie = `${name}=${encodeURIComponent(JSON.stringify(value))};expires=${expires.toUTCString()};path=/`;
|
|
4588
|
-
}
|
|
4589
4875
|
function getCookie(name) {
|
|
4590
4876
|
const nameEQ = name + "=";
|
|
4591
4877
|
const ca = document.cookie.split(';');
|
|
@@ -4605,9 +4891,6 @@ function getCookie(name) {
|
|
|
4605
4891
|
}
|
|
4606
4892
|
return null;
|
|
4607
4893
|
}
|
|
4608
|
-
function deleteCookie(name) {
|
|
4609
|
-
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/`;
|
|
4610
|
-
}
|
|
4611
4894
|
// Decode Base64 string (supports Unicode)
|
|
4612
4895
|
function decodeBase64(base64String) {
|
|
4613
4896
|
try {
|
|
@@ -4636,6 +4919,87 @@ function decodeBase64(base64String) {
|
|
|
4636
4919
|
return null;
|
|
4637
4920
|
}
|
|
4638
4921
|
}
|
|
4922
|
+
// Generate initials from username (e.g., "Jake Thai" -> "JT")
|
|
4923
|
+
function getInitialsFromName(name) {
|
|
4924
|
+
if (!name) return '?';
|
|
4925
|
+
const parts = name.trim().split(/\s+/);
|
|
4926
|
+
if (parts.length === 1) {
|
|
4927
|
+
return parts[0].charAt(0).toUpperCase();
|
|
4928
|
+
}
|
|
4929
|
+
return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();
|
|
4930
|
+
}
|
|
4931
|
+
|
|
4932
|
+
// Generate a consistent color based on the username
|
|
4933
|
+
function getAvatarColor(name) {
|
|
4934
|
+
// Microsoft Fluent UI persona colors
|
|
4935
|
+
const colors = [
|
|
4936
|
+
'#0078D4', // Microsoft Blue
|
|
4937
|
+
'#107C10', // Green
|
|
4938
|
+
'#5C2D91', // Purple
|
|
4939
|
+
'#B4009E', // Magenta
|
|
4940
|
+
'#D83B01', // Orange
|
|
4941
|
+
'#E74856', // Red
|
|
4942
|
+
'#00B7C3', // Teal
|
|
4943
|
+
'#0099BC', // Cyan
|
|
4944
|
+
'#7A7574', // Gray
|
|
4945
|
+
'#69797E', // Dark Gray
|
|
4946
|
+
'#498205', // Lime Green
|
|
4947
|
+
'#847545', // Gold
|
|
4948
|
+
'#C239B3', // Pink
|
|
4949
|
+
'#038387', // Dark Teal
|
|
4950
|
+
'#8764B8', // Light Purple
|
|
4951
|
+
'#CA5010', // Burnt Orange
|
|
4952
|
+
];
|
|
4953
|
+
// Generate a hash from the name for consistent color
|
|
4954
|
+
let hash = 0;
|
|
4955
|
+
const str = name || 'User';
|
|
4956
|
+
for (let i = 0; i < str.length; i++) {
|
|
4957
|
+
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
|
4958
|
+
}
|
|
4959
|
+
return colors[Math.abs(hash) % colors.length];
|
|
4960
|
+
}
|
|
4961
|
+
|
|
4962
|
+
// Generate avatar as base64 PNG image
|
|
4963
|
+
function generateAvatarBase64(username, size = 64) {
|
|
4964
|
+
if (typeof document === 'undefined') return null;
|
|
4965
|
+
|
|
4966
|
+
const initials = getInitialsFromName(username);
|
|
4967
|
+
const bgColor = getAvatarColor(username);
|
|
4968
|
+
|
|
4969
|
+
// Use higher resolution for crisp rendering
|
|
4970
|
+
const scale = 2;
|
|
4971
|
+
const actualSize = size * scale;
|
|
4972
|
+
|
|
4973
|
+
// Create canvas
|
|
4974
|
+
const canvas = document.createElement('canvas');
|
|
4975
|
+
canvas.width = actualSize;
|
|
4976
|
+
canvas.height = actualSize;
|
|
4977
|
+
const ctx = canvas.getContext('2d');
|
|
4978
|
+
|
|
4979
|
+
// Enable anti-aliasing
|
|
4980
|
+
ctx.imageSmoothingEnabled = true;
|
|
4981
|
+
ctx.imageSmoothingQuality = 'high';
|
|
4982
|
+
|
|
4983
|
+
// Draw circle background
|
|
4984
|
+
ctx.beginPath();
|
|
4985
|
+
ctx.arc(actualSize / 2, actualSize / 2, actualSize / 2, 0, Math.PI * 2);
|
|
4986
|
+
ctx.fillStyle = bgColor;
|
|
4987
|
+
ctx.fill();
|
|
4988
|
+
|
|
4989
|
+
// Draw initials text
|
|
4990
|
+
ctx.fillStyle = '#FFFFFF';
|
|
4991
|
+
|
|
4992
|
+
const fontSize = actualSize * 0.42;
|
|
4993
|
+
ctx.font = `400 ${fontSize}px "Segoe UI", "Segoe UI Web", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif`;
|
|
4994
|
+
ctx.textAlign = 'center';
|
|
4995
|
+
ctx.textBaseline = 'middle';
|
|
4996
|
+
|
|
4997
|
+
// Slight vertical adjustment for better visual centering
|
|
4998
|
+
ctx.fillText(initials, actualSize / 2, actualSize / 2 + (fontSize * 0.04));
|
|
4999
|
+
|
|
5000
|
+
// Return as base64
|
|
5001
|
+
return canvas.toDataURL('image/png');
|
|
5002
|
+
}
|
|
4639
5003
|
// Parse KBGateway-User-Context cookie (Base64 encoded)
|
|
4640
5004
|
function parseKBGatewayUserContext(cookieValue) {
|
|
4641
5005
|
if (!cookieValue) return null;
|
|
@@ -4661,7 +5025,7 @@ function parseKBGatewayUserContext(cookieValue) {
|
|
|
4661
5025
|
return {
|
|
4662
5026
|
username: username,
|
|
4663
5027
|
email: parsed.email || null,
|
|
4664
|
-
avatar:
|
|
5028
|
+
avatar: generateAvatarBase64(username)
|
|
4665
5029
|
};
|
|
4666
5030
|
} catch (e) {
|
|
4667
5031
|
console.warn('Failed to parse KBGateway-User-Context:', e);
|
|
@@ -4678,7 +5042,7 @@ function parseKBGatewayUserContext(cookieValue) {
|
|
|
4678
5042
|
return {
|
|
4679
5043
|
username: username,
|
|
4680
5044
|
email: parsed.email || null,
|
|
4681
|
-
avatar:
|
|
5045
|
+
avatar: generateAvatarBase64(username)
|
|
4682
5046
|
};
|
|
4683
5047
|
} catch (e2) {
|
|
4684
5048
|
console.warn('Failed to parse as JSON:', e2);
|
|
@@ -4688,54 +5052,12 @@ function parseKBGatewayUserContext(cookieValue) {
|
|
|
4688
5052
|
}
|
|
4689
5053
|
// LocalStorage key for user data
|
|
4690
5054
|
const USER_STORAGE_KEY = 'kb_user_data';
|
|
4691
|
-
|
|
4692
|
-
function getUserFromStorage() {
|
|
4693
|
-
if (typeof localStorage === 'undefined') return null;
|
|
4694
|
-
|
|
4695
|
-
try {
|
|
4696
|
-
const storedData = localStorage.getItem(USER_STORAGE_KEY);
|
|
4697
|
-
if (storedData) {
|
|
4698
|
-
return JSON.parse(storedData);
|
|
4699
|
-
}
|
|
4700
|
-
} catch (e) {
|
|
4701
|
-
console.warn('Failed to get user from localStorage:', e);
|
|
4702
|
-
localStorage.removeItem(USER_STORAGE_KEY);
|
|
4703
|
-
}
|
|
4704
|
-
return null;
|
|
4705
|
-
}
|
|
4706
|
-
// Save user data to localStorage
|
|
4707
|
-
function saveUserToStorage(userData) {
|
|
4708
|
-
if (typeof localStorage === 'undefined') return;
|
|
4709
|
-
|
|
4710
|
-
try {
|
|
4711
|
-
if (userData) {
|
|
4712
|
-
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(userData));
|
|
4713
|
-
} else {
|
|
4714
|
-
localStorage.removeItem(USER_STORAGE_KEY);
|
|
4715
|
-
}
|
|
4716
|
-
} catch (e) {
|
|
4717
|
-
console.warn('Failed to save user to localStorage:', e);
|
|
4718
|
-
}
|
|
4719
|
-
}
|
|
4720
|
-
// Remove user data from localStorage
|
|
4721
|
-
function removeUserFromStorage() {
|
|
4722
|
-
if (typeof localStorage === 'undefined') return;
|
|
4723
|
-
localStorage.removeItem(USER_STORAGE_KEY);
|
|
4724
|
-
}
|
|
4725
|
-
// Sync cookie to localStorage and return user data
|
|
4726
|
-
function syncCookieToStorage(cookieName) {
|
|
4727
|
-
const cookieValue = getCookie(cookieName);
|
|
4728
|
-
const userData = parseKBGatewayUserContext(cookieValue);
|
|
4729
|
-
|
|
4730
|
-
if (userData) {
|
|
4731
|
-
saveUserToStorage(userData);
|
|
4732
|
-
} else {
|
|
4733
|
-
removeUserFromStorage();
|
|
4734
|
-
}
|
|
4735
|
-
|
|
4736
|
-
return userData;
|
|
4737
|
-
}
|
|
5055
|
+
|
|
4738
5056
|
// User Authentication Component
|
|
5057
|
+
// Cache user data globally to prevent flicker between page navigations
|
|
5058
|
+
let cachedUserData = null;
|
|
5059
|
+
let isClientInitialized = false;
|
|
5060
|
+
|
|
4739
5061
|
function UserAuth() {
|
|
4740
5062
|
const { siteData } = (0, __WEBPACK_EXTERNAL_MODULE__rspress_runtime_0abd3046__.usePageData)();
|
|
4741
5063
|
const dropdownRef = (0, __WEBPACK_EXTERNAL_MODULE_react__.useRef)(null);
|
|
@@ -4743,52 +5065,54 @@ function UserAuth() {
|
|
|
4743
5065
|
const authEnabled = siteData?.auth?.enabled !== false;
|
|
4744
5066
|
const showSignInButton = siteData?.auth?.showSignInButton !== false;
|
|
4745
5067
|
|
|
4746
|
-
// Get sign in URL from site config
|
|
5068
|
+
// Get sign in /sign out URL from site config
|
|
4747
5069
|
const signInUrl = siteData?.auth?.endpoints?.signIn;
|
|
5070
|
+
const signOutUrl = siteData?.auth?.endpoints?.signOut;
|
|
4748
5071
|
|
|
4749
5072
|
// Cookie name for KBGateway
|
|
4750
5073
|
const KB_COOKIE_NAME = 'KBGateway-User-Context';
|
|
4751
5074
|
|
|
4752
|
-
|
|
5075
|
+
// Helper function to get user from cookie directly
|
|
5076
|
+
const getUserFromCookie = () => {
|
|
4753
5077
|
if (typeof document === 'undefined') return null;
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
5078
|
+
const cookieValue = getCookie(KB_COOKIE_NAME);
|
|
5079
|
+
return parseKBGatewayUserContext(cookieValue);
|
|
5080
|
+
};
|
|
5081
|
+
|
|
5082
|
+
// Initialize from cache first, then cookie - prevents flicker on navigation
|
|
5083
|
+
const [user, setUser] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(() => {
|
|
5084
|
+
// Use cached data first for instant render
|
|
5085
|
+
if (cachedUserData) return cachedUserData;
|
|
5086
|
+
// Fall back to cookie (only works on client)
|
|
5087
|
+
if (typeof document !== 'undefined') {
|
|
5088
|
+
const cookieUser = getUserFromCookie();
|
|
5089
|
+
if (cookieUser) {
|
|
5090
|
+
cachedUserData = cookieUser;
|
|
5091
|
+
isClientInitialized = true;
|
|
5092
|
+
}
|
|
5093
|
+
return cookieUser;
|
|
4759
5094
|
}
|
|
4760
|
-
|
|
4761
|
-
// 2. If not in localStorage, check cookie and sync
|
|
4762
|
-
return syncCookieToStorage(KB_COOKIE_NAME);
|
|
5095
|
+
return null;
|
|
4763
5096
|
});
|
|
4764
5097
|
|
|
5098
|
+
// Track if component has mounted (for SSR hydration)
|
|
5099
|
+
const [isMounted, setIsMounted] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(isClientInitialized);
|
|
5100
|
+
|
|
4765
5101
|
const [showDropdown, setShowDropdown] = (0, __WEBPACK_EXTERNAL_MODULE_react__.useState)(false);
|
|
4766
5102
|
|
|
4767
|
-
//
|
|
5103
|
+
// Check cookie on mount and update cache
|
|
4768
5104
|
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(() => {
|
|
4769
|
-
|
|
4770
|
-
const userData = syncCookieToStorage(KB_COOKIE_NAME);
|
|
5105
|
+
const userData = getUserFromCookie();
|
|
4771
5106
|
if (userData) {
|
|
5107
|
+
cachedUserData = userData;
|
|
4772
5108
|
setUser(userData);
|
|
5109
|
+
} else if (isClientInitialized) {
|
|
5110
|
+
// Cookie was removed (signed out) - only clear if we were initialized
|
|
5111
|
+
cachedUserData = null;
|
|
5112
|
+
setUser(null);
|
|
4773
5113
|
}
|
|
4774
|
-
|
|
4775
|
-
|
|
4776
|
-
const handleStorageChange = (e) => {
|
|
4777
|
-
if (e.key === USER_STORAGE_KEY) {
|
|
4778
|
-
if (e.newValue) {
|
|
4779
|
-
try {
|
|
4780
|
-
setUser(JSON.parse(e.newValue));
|
|
4781
|
-
} catch (err) {
|
|
4782
|
-
setUser(null);
|
|
4783
|
-
}
|
|
4784
|
-
} else {
|
|
4785
|
-
setUser(null);
|
|
4786
|
-
}
|
|
4787
|
-
}
|
|
4788
|
-
};
|
|
4789
|
-
|
|
4790
|
-
window.addEventListener('storage', handleStorageChange);
|
|
4791
|
-
return () => window.removeEventListener('storage', handleStorageChange);
|
|
5114
|
+
isClientInitialized = true;
|
|
5115
|
+
setIsMounted(true);
|
|
4792
5116
|
}, []);
|
|
4793
5117
|
|
|
4794
5118
|
(0, __WEBPACK_EXTERNAL_MODULE_react__.useEffect)(() => {
|
|
@@ -4803,96 +5127,43 @@ function UserAuth() {
|
|
|
4803
5127
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
4804
5128
|
}, []);
|
|
4805
5129
|
|
|
4806
|
-
const handleSignIn =
|
|
5130
|
+
const handleSignIn = () => {
|
|
4807
5131
|
if (!signInUrl) {
|
|
4808
5132
|
console.warn('Sign in URL not configured');
|
|
4809
5133
|
return;
|
|
4810
5134
|
}
|
|
4811
5135
|
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
const width = 600;
|
|
4815
|
-
const height = 600;
|
|
4816
|
-
const left = window.top.outerWidth / 2 + window.top.screenX - width / 2;
|
|
4817
|
-
const top = window.top.outerHeight / 2 + window.top.screenY - height / 2;
|
|
4818
|
-
|
|
4819
|
-
// Open sign in URL in new window/tab
|
|
4820
|
-
const authWindow = window.open(signInUrl, '_blank', `width=${width},height=${height},left=${left},top=${top}`);
|
|
4821
|
-
|
|
4822
|
-
// Listen for messages from auth window
|
|
4823
|
-
const handleMessage = (event) => {
|
|
4824
|
-
if (event.origin !== new URL(signInUrl).origin) return;
|
|
4825
|
-
|
|
4826
|
-
if (event.data && event.data.type === 'AUTH_SUCCESS') {
|
|
4827
|
-
const userData = {
|
|
4828
|
-
username: event.data.username,
|
|
4829
|
-
email: event.data.email,
|
|
4830
|
-
avatar: event.data.avatar
|
|
4831
|
-
};
|
|
4832
|
-
|
|
4833
|
-
// Save to localStorage
|
|
4834
|
-
saveUserToStorage(userData);
|
|
4835
|
-
setUser(userData);
|
|
4836
|
-
authWindow.close();
|
|
4837
|
-
|
|
4838
|
-
// Remove event listener
|
|
4839
|
-
window.removeEventListener('message', handleMessage);
|
|
4840
|
-
}
|
|
4841
|
-
};
|
|
4842
|
-
|
|
4843
|
-
window.addEventListener('message', handleMessage);
|
|
4844
|
-
|
|
4845
|
-
// Poll for KBGateway-User-Context cookie
|
|
4846
|
-
const pollInterval = setInterval(() => {
|
|
4847
|
-
// Sync cookie to localStorage and get user data
|
|
4848
|
-
const userData = syncCookieToStorage(KB_COOKIE_NAME);
|
|
4849
|
-
|
|
4850
|
-
if (userData) {
|
|
4851
|
-
setUser(userData);
|
|
4852
|
-
clearInterval(pollInterval);
|
|
4853
|
-
window.removeEventListener('message', handleMessage);
|
|
4854
|
-
|
|
4855
|
-
// Close popup if still open
|
|
4856
|
-
if (authWindow && !authWindow.closed) {
|
|
4857
|
-
authWindow.close();
|
|
4858
|
-
}
|
|
4859
|
-
}
|
|
4860
|
-
|
|
4861
|
-
// Also check if popup was closed manually
|
|
4862
|
-
if (authWindow && authWindow.closed) {
|
|
4863
|
-
clearInterval(pollInterval);
|
|
4864
|
-
window.removeEventListener('message', handleMessage);
|
|
4865
|
-
|
|
4866
|
-
// Final sync cookie to localStorage
|
|
4867
|
-
const finalUserData = syncCookieToStorage(KB_COOKIE_NAME);
|
|
4868
|
-
if (finalUserData) {
|
|
4869
|
-
setUser(finalUserData);
|
|
4870
|
-
}
|
|
4871
|
-
}
|
|
4872
|
-
}, 500); // Check every 500ms
|
|
4873
|
-
|
|
4874
|
-
// Timeout after 5 minutes
|
|
4875
|
-
setTimeout(() => {
|
|
4876
|
-
clearInterval(pollInterval);
|
|
4877
|
-
window.removeEventListener('message', handleMessage);
|
|
4878
|
-
}, 300000);
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
} catch (error) {
|
|
4882
|
-
console.error('Sign in error:', error);
|
|
4883
|
-
}
|
|
5136
|
+
// Redirect directly to sign in URL
|
|
5137
|
+
window.location.href = signInUrl;
|
|
4884
5138
|
};
|
|
4885
5139
|
|
|
4886
5140
|
const handleSignOut = () => {
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
5141
|
+
if (!signOutUrl) {
|
|
5142
|
+
console.warn('Sign out URL not configured');
|
|
5143
|
+
return;
|
|
5144
|
+
}
|
|
5145
|
+
fetch(signOutUrl)
|
|
5146
|
+
.then(() => {
|
|
5147
|
+
cachedUserData = null; // Clear cache on sign out
|
|
5148
|
+
setUser(null);
|
|
5149
|
+
setShowDropdown(false);
|
|
5150
|
+
})
|
|
5151
|
+
.catch((error) => {
|
|
5152
|
+
console.error('Error signing out:', error);
|
|
5153
|
+
});
|
|
4891
5154
|
};
|
|
4892
5155
|
|
|
4893
5156
|
if (!authEnabled) {
|
|
4894
5157
|
return null;
|
|
4895
5158
|
}
|
|
5159
|
+
|
|
5160
|
+
// Don't render anything until client is mounted to prevent hydration mismatch
|
|
5161
|
+
if (!isMounted) {
|
|
5162
|
+
// Return a placeholder with same dimensions to prevent layout shift
|
|
5163
|
+
return (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("div", {
|
|
5164
|
+
style: { width: '28px', height: '28px' }
|
|
5165
|
+
});
|
|
5166
|
+
}
|
|
4896
5167
|
|
|
4897
5168
|
if (!user) {
|
|
4898
5169
|
if (!showSignInButton) {
|
|
@@ -4909,7 +5180,7 @@ function UserAuth() {
|
|
|
4909
5180
|
});
|
|
4910
5181
|
}
|
|
4911
5182
|
|
|
4912
|
-
const userAvatar = user.avatar
|
|
5183
|
+
const userAvatar = user.avatar;
|
|
4913
5184
|
|
|
4914
5185
|
return (0, __WEBPACK_EXTERNAL_MODULE_react_jsx_runtime_225474f2__.jsx)("div", {
|
|
4915
5186
|
className: "relative",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
2
|
"name": "@rspress-theme-anatole/theme-default",
|
|
3
3
|
"author": "Anatole Tong",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.23",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"sideEffects": [
|
|
7
7
|
"*.css",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"types": "./dist/bundle.d.ts",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@mdx-js/react": "2.3.0",
|
|
24
|
-
"@rspress-theme-anatole/rspress-plugin-mermaid": "0.7.
|
|
25
|
-
"@rspress-theme-anatole/shared": "0.7.
|
|
24
|
+
"@rspress-theme-anatole/rspress-plugin-mermaid": "0.7.23",
|
|
25
|
+
"@rspress-theme-anatole/shared": "0.7.23",
|
|
26
26
|
"@rspress/runtime": "1.43.8",
|
|
27
27
|
"body-scroll-lock": "4.0.0-beta.0",
|
|
28
28
|
"copy-to-clipboard": "^3.3.3",
|