Skip to content

Commit c001411

Browse files
Merge branch 'main' into viktor/rnd-3264/table-widths-to-flex
2 parents 2ff1075 + 29a0d7e commit c001411

File tree

18 files changed

+333
-95
lines changed

18 files changed

+333
-95
lines changed

.github/actions/setup-playwright/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ runs:
1212
1313
# Cache browser binaries, cache key is based on Playwright version and OS
1414
- name: 🧰 Cache Playwright browser binaries
15-
uses: actions/cache@v3
15+
uses: actions/cache@v4
1616
id: playwright-cache
1717
with:
1818
path: '~/.cache/ms-playwright'

.github/workflows/ci.yaml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,6 @@ jobs:
3030
run: bun install --frozen-lockfile
3131
env:
3232
PUPPETEER_SKIP_DOWNLOAD: 1
33-
- name: Cache Next.js build
34-
uses: actions/cache@v3
35-
with:
36-
path: |
37-
${{ github.workspace }}/.next/cache
38-
# Generate a new cache whenever packages or source files change.
39-
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/bun.lockb') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
40-
# If source files changed but packages didn't, rebuild from a prior cache.
41-
restore-keys: |
42-
${{ runner.os }}-nextjs-${{ hashFiles('**/bun.lockb') }}-
4333
- name: Sets env vars for production
4434
run: |
4535
echo "SENTRY_ENVIRONMENT=production" >> $GITHUB_ENV

bun.lockb

100755100644
File mode changed.

packages/gitbook/e2e/pages.spec.ts

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import {
1010
SiteCustomizationSettings,
1111
} from '@gitbook/api';
1212
import { test, expect, Page } from '@playwright/test';
13+
import deepMerge from 'deepmerge';
1314
import jwt from 'jsonwebtoken';
1415
import rison from 'rison';
1516
import { DeepPartial } from 'ts-essentials';
16-
import deepMerge from 'deepmerge';
1717

1818
import { getContentTestURL } from '../tests/utils';
1919

@@ -930,6 +930,94 @@ const testCases: TestsCase[] = [
930930
},
931931
],
932932
},
933+
{
934+
name: 'Adaptive Content - VA',
935+
baseUrl: `https://gitbook-open-e2e-sites.gitbook.io/adaptive-content-va/`,
936+
tests: [
937+
{
938+
name: 'isAlphaUser',
939+
url: (() => {
940+
const privateKey = 'afe09cdf-0f43-480a-b54c-8b1f62f174f9';
941+
const token = jwt.sign(
942+
{
943+
name: 'gitbook-open-tests',
944+
isAlphaUser: true,
945+
},
946+
privateKey,
947+
{
948+
expiresIn: '24h',
949+
},
950+
);
951+
return `?jwt_token=${token}`;
952+
})(),
953+
run: async (page) => {
954+
const alphaUserPage = page
955+
.locator('a[class*="group\\/toclink"]')
956+
.filter({ hasText: 'Alpha users' });
957+
const betaUserPage = page
958+
.locator('a[class*="group\\/toclink"]')
959+
.filter({ hasText: 'Beta users' });
960+
await expect(alphaUserPage).toBeVisible();
961+
await expect(betaUserPage).toHaveCount(0);
962+
},
963+
},
964+
{
965+
name: 'isBetaUser',
966+
url: (() => {
967+
const privateKey = 'afe09cdf-0f43-480a-b54c-8b1f62f174f9';
968+
const token = jwt.sign(
969+
{
970+
name: 'gitbook-open-tests',
971+
isBetaUser: true,
972+
},
973+
privateKey,
974+
{
975+
expiresIn: '24h',
976+
},
977+
);
978+
return `?jwt_token=${token}`;
979+
})(),
980+
run: async (page) => {
981+
const alphaUserPage = page
982+
.locator('a[class*="group\\/toclink"]')
983+
.filter({ hasText: 'Alpha users' });
984+
const betaUserPage = page
985+
.locator('a[class*="group\\/toclink"]')
986+
.filter({ hasText: 'Beta users' });
987+
await expect(betaUserPage).toBeVisible();
988+
await expect(alphaUserPage).toHaveCount(0);
989+
},
990+
},
991+
{
992+
name: 'isAlphaUser & isBetaUser',
993+
url: (() => {
994+
const privateKey = 'afe09cdf-0f43-480a-b54c-8b1f62f174f9';
995+
const token = jwt.sign(
996+
{
997+
name: 'gitbook-open-tests',
998+
isAlphaUser: true,
999+
isBetaUser: true,
1000+
},
1001+
privateKey,
1002+
{
1003+
expiresIn: '24h',
1004+
},
1005+
);
1006+
return `?jwt_token=${token}`;
1007+
})(),
1008+
run: async (page) => {
1009+
const alphaUserPage = page
1010+
.locator('a[class*="group\\/toclink"]')
1011+
.filter({ hasText: 'Alpha users' });
1012+
const betaUserPage = page
1013+
.locator('a[class*="group\\/toclink"]')
1014+
.filter({ hasText: 'Beta users' });
1015+
await expect(alphaUserPage).toBeVisible();
1016+
await expect(betaUserPage).toBeVisible();
1017+
},
1018+
},
1019+
],
1020+
},
9331021
];
9341022

9351023
for (const testCase of testCases) {

packages/gitbook/src/app/(site)/(content)/[[...pathname]]/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ export async function generateMetadata({
150150
.join(' | '),
151151
description: page.description ?? '',
152152
alternates: {
153-
canonical: absoluteHref(getPagePath(pages, page), true),
153+
// Trim trailing slashes in canonical URL to match the redirect behavior
154+
canonical: absoluteHref(getPagePath(pages, page), true).replace(/\/+$/, ''),
154155
},
155156
openGraph: {
156157
images: [

packages/gitbook/src/app/(site)/(content)/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default async function ContentLayout(props: { children: React.ReactNode }
4242
sections,
4343
} = await fetchContentData();
4444

45-
ReactDOM.preconnect(api().endpoint);
45+
ReactDOM.preconnect(api().client.endpoint);
4646
if (assetsDomain) {
4747
ReactDOM.preconnect(assetsDomain);
4848
}

packages/gitbook/src/components/Header/Dropdown.tsx

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export function Dropdown<E extends HTMLElement>(props: {
3939
aria-labelledby={dropdownId}
4040
className={tcls(
4141
'w-52',
42-
'max-h-56',
42+
'max-h-80',
4343
'flex',
4444
'absolute',
4545
'top-full',
@@ -111,31 +111,38 @@ export function DropdownMenu(props: { children: React.ReactNode }) {
111111
* Menu item in a dropdown.
112112
*/
113113
export function DropdownMenuItem(props: {
114-
href: string;
114+
href: string | null;
115115
active?: boolean;
116+
className?: ClassValue;
116117
children: React.ReactNode;
117118
}) {
118-
const { children, active = false, href } = props;
119+
const { children, active = false, href, className } = props;
120+
121+
if (href) {
122+
return (
123+
<Link
124+
href={href}
125+
prefetch={false}
126+
className={tcls(
127+
'px-3 py-1 text-sm rounded straight-corners:rounded-sm',
128+
active ? 'bg-primary/3 dark:bg-light/2 text-primary-600' : null,
129+
'hover:bg-dark/2 dark:hover:bg-light/2',
130+
className,
131+
)}
132+
>
133+
{children}
134+
</Link>
135+
);
136+
}
119137

120138
return (
121-
<Link
122-
href={href}
123-
prefetch={false}
139+
<div
124140
className={tcls(
125-
'flex',
126-
'flex-row',
127-
'items-center',
128-
'text-sm',
129-
'px-3',
130-
'py-1',
131-
'rounded',
132-
'straight-corners:rounded-sm',
133-
active
134-
? ['bg-primary/3', 'dark:bg-light/2', 'text-primary-600']
135-
: ['hover:bg-dark/2', 'dark:hover:bg-light/2'],
141+
'text-xs px-3 py-1 font-medium text-dark/8 dark:text-light/8',
142+
className,
136143
)}
137144
>
138145
{children}
139-
</Link>
146+
</div>
140147
);
141148
}

packages/gitbook/src/components/Header/HeaderLink.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ function HeaderItemButton(
104104
linkStyle: 'button-secondary' | 'button-primary';
105105
},
106106
) {
107-
const { linkStyle, headerPreset, title, href, ...rest } = props;
107+
const { linkStyle, headerPreset, title, href, isDropdown, ...rest } = props;
108108
const variant = (() => {
109109
switch (linkStyle) {
110110
case 'button-secondary':

packages/gitbook/src/components/Header/HeaderLinkMore.tsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
CustomizationContentLink,
23
CustomizationHeaderItem,
34
CustomizationHeaderPreset,
45
CustomizationSettings,
@@ -55,14 +56,25 @@ export function HeaderLinkMore(props: {
5556
);
5657
}
5758

58-
async function MoreMenuLink(props: { context: ContentRefContext; link: CustomizationHeaderItem }) {
59+
async function MoreMenuLink(props: {
60+
context: ContentRefContext;
61+
link: CustomizationHeaderItem | CustomizationContentLink;
62+
}) {
5963
const { context, link } = props;
6064

6165
const target = link.to ? await resolveContentRef(link.to, context) : null;
6266

63-
if (!target) {
64-
return null;
65-
}
66-
67-
return <DropdownMenuItem href={target.href}>{link.title}</DropdownMenuItem>;
67+
return (
68+
<>
69+
{'links' in link && link.links.length > 0 && (
70+
<hr className="first:hidden border-t border-light-3 dark:border-dark-3 my-1 -mx-2" />
71+
)}
72+
<DropdownMenuItem href={target?.href ?? null}>{link.title}</DropdownMenuItem>
73+
{'links' in link
74+
? link.links.map((subLink, index) => (
75+
<MoreMenuLink key={index} {...props} link={subLink} />
76+
))
77+
: null}
78+
</>
79+
);
6880
}

packages/gitbook/src/components/PageBody/PageBody.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export function PageBody(props: {
148148
sitePointer={pointer}
149149
spaceId={space.id}
150150
pageId={page.id}
151-
apiHost={api().endpoint}
151+
apiHost={api().client.endpoint}
152152
/>
153153
) : null}
154154
</>

0 commit comments

Comments
 (0)