mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-21 01:53:26 +00:00
Merge remote-tracking branch 'origin/main' into stevenh/bump-shiki
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"gitbook": patch
|
||||
---
|
||||
|
||||
AI response feedback buttons
|
||||
@@ -246,7 +246,7 @@
|
||||
"react-dom": "^19.0.0",
|
||||
},
|
||||
"catalog": {
|
||||
"@gitbook/api": "^0.128.0",
|
||||
"@gitbook/api": "^0.129.0",
|
||||
},
|
||||
"packages": {
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@1.1.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-0M+qjp+clUD0R1E5eWQFhxEvWLNaOtGQRUaBn8CUABnSKredagq92hUS9VjOzGsTm37xLfpaxl97AVtbeOsHew=="],
|
||||
@@ -609,7 +609,7 @@
|
||||
|
||||
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@6.6.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.6.0" } }, "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg=="],
|
||||
|
||||
"@gitbook/api": ["@gitbook/api@0.128.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-VO98hRGfUcFdwMplvFW49jz72/ew2waE7RCu+URKAY2AyPHAduv2zgluF5gF1VcDyuJM9PKFtsdsMtpUjI5sYg=="],
|
||||
"@gitbook/api": ["@gitbook/api@0.129.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-Uh+k/BiDgdXj5a8BIlvwfEXdZNNlQMFDlGKmivUYH1gvFySqrTO6PjR/HtUOZEdNauAeWZmGoB8CLuwrVZS+YA=="],
|
||||
|
||||
"@gitbook/cache-tags": ["@gitbook/cache-tags@workspace:packages/cache-tags"],
|
||||
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@
|
||||
"workspaces": {
|
||||
"packages": ["packages/*"],
|
||||
"catalog": {
|
||||
"@gitbook/api": "^0.128.0"
|
||||
"@gitbook/api": "^0.129.0"
|
||||
}
|
||||
},
|
||||
"patchedDependencies": {
|
||||
|
||||
@@ -90,7 +90,7 @@ export function getCacheTag(
|
||||
| {
|
||||
tag: 'translation';
|
||||
organization: string;
|
||||
translationSettings: string;
|
||||
translation: string;
|
||||
}
|
||||
): string {
|
||||
switch (spec.tag) {
|
||||
@@ -115,7 +115,7 @@ export function getCacheTag(
|
||||
case 'openapi':
|
||||
return `organization:${spec.organization}:openapi:${spec.openAPISpec}`;
|
||||
case 'translation':
|
||||
return `organization:${spec.organization}:translation:${spec.translationSettings}`;
|
||||
return `organization:${spec.organization}:translation:${spec.translation}`;
|
||||
default:
|
||||
assertNever(spec);
|
||||
}
|
||||
@@ -144,6 +144,10 @@ export function getComputedContentSourceCacheTags(
|
||||
) {
|
||||
const tags: string[] = [];
|
||||
|
||||
if (!('dependencies' in source)) {
|
||||
return tags;
|
||||
}
|
||||
|
||||
// We add the dependencies as tags, to ensure that the computed content is invalidated
|
||||
// when the dependencies are updated.
|
||||
const dependencies = Object.values(source.dependencies ?? {});
|
||||
@@ -167,12 +171,12 @@ export function getComputedContentSourceCacheTags(
|
||||
})
|
||||
);
|
||||
break;
|
||||
case 'translation-language':
|
||||
case 'translation':
|
||||
tags.push(
|
||||
getCacheTag({
|
||||
tag: 'translation',
|
||||
organization: inContext.organizationId,
|
||||
translationSettings: dependency.ref.translationSettings,
|
||||
translation: dependency.ref.translation,
|
||||
})
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -318,10 +318,6 @@ export function getCustomizationURL(partial: DeepPartial<SiteCustomizationSettin
|
||||
feedback: {
|
||||
enabled: false,
|
||||
},
|
||||
// TODO: remove aiSearch once the cache has been fully updated (after 11/07/2025)
|
||||
aiSearch: {
|
||||
enabled: true,
|
||||
},
|
||||
ai: {
|
||||
mode: CustomizationAIMode.None,
|
||||
},
|
||||
@@ -337,6 +333,10 @@ export function getCustomizationURL(partial: DeepPartial<SiteCustomizationSettin
|
||||
pagination: {
|
||||
enabled: true,
|
||||
},
|
||||
pageActions: {
|
||||
externalAI: true,
|
||||
markdown: true,
|
||||
},
|
||||
trademark: {
|
||||
enabled: true,
|
||||
},
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useAIMessageContextRef } from './useAIMessageContext';
|
||||
export type AIChatMessage = {
|
||||
role: AIMessageRole;
|
||||
content: React.ReactNode;
|
||||
query?: string;
|
||||
};
|
||||
|
||||
export type AIChatState = {
|
||||
@@ -24,6 +25,11 @@ export type AIChatState = {
|
||||
*/
|
||||
responseId: string | null;
|
||||
|
||||
/**
|
||||
* The latest query sent to the AI.
|
||||
*/
|
||||
query: string | null;
|
||||
|
||||
/**
|
||||
* Messages in the session.
|
||||
*/
|
||||
@@ -73,6 +79,7 @@ const globalState = zustand.create<{
|
||||
opened: false,
|
||||
responseId: null,
|
||||
messages: [],
|
||||
query: null,
|
||||
followUpSuggestions: [],
|
||||
loading: false,
|
||||
error: false,
|
||||
@@ -106,6 +113,7 @@ export function useAIChatController(): AIChatController {
|
||||
opened: state.opened,
|
||||
loading: false,
|
||||
messages: [],
|
||||
query: null,
|
||||
followUpSuggestions: [],
|
||||
responseId: null,
|
||||
error: false,
|
||||
@@ -128,6 +136,7 @@ export function useAIChatController(): AIChatController {
|
||||
content: null,
|
||||
},
|
||||
],
|
||||
query: input.message,
|
||||
followUpSuggestions: [],
|
||||
loading: true,
|
||||
error: false,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { tcls } from '@/lib/tailwind';
|
||||
import { AIMessageRole } from '@gitbook/api';
|
||||
import type React from 'react';
|
||||
import type { AIChatController, AIChatState } from '../AI/useAIChat';
|
||||
import { AIResponseFeedback } from './AIResponseFeedback';
|
||||
import { AIChatFollowupSuggestions } from './AiChatFollowupSuggestions';
|
||||
|
||||
export function AIChatMessages(props: {
|
||||
@@ -57,10 +58,19 @@ export function AIChatMessages(props: {
|
||||
) : null}
|
||||
|
||||
{isLastMessage ? (
|
||||
<AIChatFollowupSuggestions
|
||||
chat={chat}
|
||||
chatController={chatController}
|
||||
/>
|
||||
<>
|
||||
{!chat.loading && !chat.error && chat.query && chat.responseId && (
|
||||
<AIResponseFeedback
|
||||
responseId={chat.responseId}
|
||||
query={chat.query}
|
||||
className="-ml-1 -mt-4"
|
||||
/>
|
||||
)}
|
||||
<AIChatFollowupSuggestions
|
||||
chat={chat}
|
||||
chatController={chatController}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
'use client';
|
||||
|
||||
import { useLanguage } from '@/intl/client';
|
||||
import { t, tString } from '@/intl/translate';
|
||||
import { type ClassValue, tcls } from '@/lib/tailwind';
|
||||
import { useState } from 'react';
|
||||
import { useTrackEvent } from '../Insights';
|
||||
import { Button } from '../primitives';
|
||||
|
||||
export function AIResponseFeedback(props: {
|
||||
className?: ClassValue;
|
||||
responseId: string;
|
||||
query: string;
|
||||
}) {
|
||||
const { className, responseId, query } = props;
|
||||
|
||||
const language = useLanguage();
|
||||
const [rating, setRating] = useState<1 | -1 | null>(null);
|
||||
const trackEvent = useTrackEvent();
|
||||
|
||||
const handleRating = (rating: 1 | -1) => {
|
||||
setRating(rating);
|
||||
trackEvent({ type: 'ask_rate_response', query, responseId, rating });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={tcls('flex h-fit items-center', className)}>
|
||||
<Button
|
||||
icon="thumbs-up"
|
||||
iconOnly
|
||||
label={tString(language, 'was_this_helpful_positive_label')}
|
||||
variant="blank"
|
||||
className={tcls(
|
||||
'animate-fadeIn overflow-hidden text-tint-subtle transition-all',
|
||||
rating !== null && rating !== 1 && 'px-0 text-[0] opacity-0'
|
||||
)}
|
||||
size="medium"
|
||||
style={{ animationDuration: '.5s' }}
|
||||
onClick={() => handleRating(1)}
|
||||
disabled={rating !== null}
|
||||
active={rating === 1}
|
||||
key="positive"
|
||||
/>
|
||||
<Button
|
||||
icon="thumbs-down"
|
||||
iconOnly
|
||||
label={tString(language, 'was_this_helpful_negative_label')}
|
||||
variant="blank"
|
||||
className={tcls(
|
||||
'animate-fadeIn overflow-hidden text-tint-subtle transition-all',
|
||||
rating !== null && rating !== -1 && 'px-0 text-[0] opacity-0'
|
||||
)}
|
||||
size="medium"
|
||||
style={{ animationDelay: '.2s', animationDuration: '.5s' }}
|
||||
onClick={() => handleRating(-1)}
|
||||
disabled={rating !== null}
|
||||
active={rating === -1}
|
||||
key="negative"
|
||||
/>
|
||||
{rating !== null ? (
|
||||
<span
|
||||
className="ml-2 animate-fadeIn text-tint-subtle"
|
||||
style={{ animationDelay: '.3s', animationDuration: '.5s' }}
|
||||
>
|
||||
{t(language, 'was_this_helpful_thank_you')}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './AIChat';
|
||||
export * from './AIChatButton';
|
||||
export * from './AIChatIcon';
|
||||
export * from './AIResponseFeedback';
|
||||
|
||||
@@ -10,6 +10,7 @@ import { t } from '@/intl/translate';
|
||||
import type { TranslationLanguage } from '@/intl/translations';
|
||||
import { tcls } from '@/lib/tailwind';
|
||||
|
||||
import { AIResponseFeedback } from '../AIChat';
|
||||
import { useTrackEvent } from '../Insights';
|
||||
import { Link } from '../primitives';
|
||||
import { useSearchAskContext } from './SearchAskContext';
|
||||
@@ -97,7 +98,11 @@ export function SearchAskAnswer(props: { query: string }) {
|
||||
<div className="flex min-h-full p-4">
|
||||
{askState?.type === 'answer' ? (
|
||||
<React.Suspense fallback={loading}>
|
||||
<TransitionAnswerBody answer={askState.answer} placeholder={loading} />
|
||||
<TransitionAnswerBody
|
||||
answer={askState.answer}
|
||||
placeholder={loading}
|
||||
query={query}
|
||||
/>
|
||||
</React.Suspense>
|
||||
) : null}
|
||||
{askState?.type === 'error' ? (
|
||||
@@ -114,8 +119,12 @@ export function SearchAskAnswer(props: { query: string }) {
|
||||
* Since the answer can be an async component that could suspend rendering,
|
||||
* we need to wrap it in a transition to avoid flickering.
|
||||
*/
|
||||
function TransitionAnswerBody(props: { answer: AskAnswerResult; placeholder: React.ReactNode }) {
|
||||
const { answer, placeholder } = props;
|
||||
function TransitionAnswerBody(props: {
|
||||
query: string;
|
||||
answer: AskAnswerResult;
|
||||
placeholder: React.ReactNode;
|
||||
}) {
|
||||
const { query, answer, placeholder } = props;
|
||||
const [display, setDisplay] = React.useState<AskAnswerResult | null>(null);
|
||||
const [_isPending, startTransition] = React.useTransition();
|
||||
|
||||
@@ -127,21 +136,25 @@ function TransitionAnswerBody(props: { answer: AskAnswerResult; placeholder: Rea
|
||||
|
||||
return display ? (
|
||||
<div className={tcls('w-full')}>
|
||||
<AnswerBody answer={display} />
|
||||
<AnswerBody query={query} answer={display} />
|
||||
</div>
|
||||
) : (
|
||||
<>{placeholder}</>
|
||||
);
|
||||
}
|
||||
|
||||
function AnswerBody(props: { answer: AskAnswerResult }) {
|
||||
const { answer } = props;
|
||||
function AnswerBody(props: { query: string; answer: AskAnswerResult }) {
|
||||
const { query, answer } = props;
|
||||
const language = useLanguage();
|
||||
|
||||
return (
|
||||
<>
|
||||
<div data-testid="search-ask-answer" className="text-tint-strong">
|
||||
{answer.body ?? t(language, 'search_ask_no_answer')}
|
||||
{answer.sources.length > 0 ? (
|
||||
// @TODO: Add responseId once search uses new AI endpoint
|
||||
<AIResponseFeedback query={query} className="-ml-1 mt-2" responseId="" />
|
||||
) : null}
|
||||
{answer.followupQuestions.length > 0 ? (
|
||||
<AnswerFollowupQuestions followupQuestions={answer.followupQuestions} />
|
||||
) : null}
|
||||
@@ -162,7 +175,7 @@ function AnswerFollowupQuestions(props: { followupQuestions: string[] }) {
|
||||
const getSearchLinkProps = useSearchLink();
|
||||
|
||||
return (
|
||||
<div className={tcls('flex', 'flex-col', 'flex-wrap', 'mt-4', 'sm:mt-6')}>
|
||||
<div className={tcls('flex', 'flex-col', 'flex-wrap', 'mt-4')}>
|
||||
{followupQuestions.map((question) => (
|
||||
<Link
|
||||
key={question}
|
||||
|
||||
@@ -31,6 +31,8 @@ export const variantClasses = {
|
||||
'hover:text-contrast-primary-solid-hover',
|
||||
'border-0',
|
||||
'contrast-more:border-1',
|
||||
'disabled:bg-tint',
|
||||
'disabled:text-tint/8',
|
||||
],
|
||||
blank: [
|
||||
'bg-transparent',
|
||||
@@ -42,6 +44,8 @@ export const variantClasses = {
|
||||
'hover:scale-1',
|
||||
'contrast-more:bg-tint-subtle',
|
||||
'depth-subtle:hover:translate-y-0',
|
||||
'disabled:text-tint/8',
|
||||
'disabled:bg-transparent',
|
||||
],
|
||||
secondary: [
|
||||
'bg-tint',
|
||||
@@ -51,6 +55,8 @@ export const variantClasses = {
|
||||
'depth-flat:hover:bg-tint-hover',
|
||||
'hover:text-primary',
|
||||
'contrast-more:bg-tint-subtle',
|
||||
'disabled:bg-transparent',
|
||||
'disabled:text-tint/8',
|
||||
],
|
||||
header: [
|
||||
'bg-tint-base text-tint',
|
||||
@@ -75,7 +81,7 @@ export const variantClasses = {
|
||||
|
||||
const activeClasses = {
|
||||
primary: 'bg-primary-solid-hover',
|
||||
blank: 'bg-primary-active text-primary-strong font-medium hover:text-primary-strong hover:bg-primary-active',
|
||||
blank: 'bg-primary-active disabled:bg-primary-active text-primary-strong font-medium hover:text-primary-strong disabled:text-primary-strong hover:bg-primary-active',
|
||||
secondary: 'bg-tint-active',
|
||||
header: 'bg-header-link/3',
|
||||
};
|
||||
@@ -99,13 +105,14 @@ export const Button = React.forwardRef<
|
||||
children,
|
||||
active,
|
||||
trailing,
|
||||
disabled,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const sizes = {
|
||||
default: ['text-base', 'font-semibold', 'px-5', 'py-2', 'circular-corners:px-6'],
|
||||
medium: ['text-sm', 'px-3.5', 'py-1.5', 'circular-corners:px-4'],
|
||||
medium: ['text-sm', iconOnly ? 'px-2' : 'px-3.5', 'py-1.5', 'circular-corners:px-4'],
|
||||
small: ['text-xs', 'py-2', iconOnly ? 'px-2' : 'px-3'],
|
||||
xsmall: ['text-xs', 'py-1', iconOnly ? 'px-1.5' : 'px-2'],
|
||||
};
|
||||
@@ -142,6 +149,7 @@ export const Button = React.forwardRef<
|
||||
classNames={['ButtonStyles']}
|
||||
insights={insights}
|
||||
aria-label={label?.toString()}
|
||||
aria-pressed={active === undefined ? undefined : active}
|
||||
target={target}
|
||||
{...rest}
|
||||
>
|
||||
@@ -156,12 +164,24 @@ export const Button = React.forwardRef<
|
||||
type="button"
|
||||
className={tcls(buttonOnlyClassNames, domClassName)}
|
||||
aria-label={label?.toString()}
|
||||
aria-pressed={active === undefined ? undefined : active}
|
||||
disabled={disabled}
|
||||
{...rest}
|
||||
>
|
||||
{content}
|
||||
</button>
|
||||
);
|
||||
|
||||
return iconOnly && label ? <Tooltip label={label}>{button}</Tooltip> : button;
|
||||
return iconOnly && label ? (
|
||||
<Tooltip
|
||||
rootProps={{ open: disabled === true ? false : undefined }}
|
||||
label={label}
|
||||
triggerProps={{ disabled }}
|
||||
>
|
||||
{button}
|
||||
</Tooltip>
|
||||
) : (
|
||||
button
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -33,12 +33,9 @@ export const ButtonStyles = [
|
||||
'shrink-0',
|
||||
'truncate',
|
||||
|
||||
'disabled:opacity-50',
|
||||
'disabled:cursor-not-allowed',
|
||||
'disabled:bg-tint',
|
||||
'disabled:text-tint/8',
|
||||
'disabled:shadow-none',
|
||||
'disabled:hover:scale-100',
|
||||
'disabled:!translate-y-0',
|
||||
'disabled:!shadow-none',
|
||||
] as ClassValue[];
|
||||
|
||||
export const CardStyles = [
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import type { GitBookSiteContext } from '@/lib/context';
|
||||
import { CustomizationAIMode } from '@gitbook/api';
|
||||
|
||||
// TODO: remove aiSearch and optional chain once the cache has been fully updated (after 11/07/2025)
|
||||
export const isAIChatEnabled = (context: GitBookSiteContext) =>
|
||||
context.customization.ai?.mode === CustomizationAIMode.Assistant &&
|
||||
(context.site.id === 'site_p4Xo4' || context.site.id === 'site_JOVzv');
|
||||
context.customization.ai.mode === CustomizationAIMode.Assistant;
|
||||
|
||||
@@ -32,6 +32,8 @@ export const de = {
|
||||
was_this_helpful_negative: 'Nein',
|
||||
was_this_helpful_thank_you: 'Danke!',
|
||||
was_this_helpful_comment: 'Möchten Sie etwas hinzufügen?',
|
||||
was_this_helpful_positive_label: 'Hilfreich',
|
||||
was_this_helpful_negative_label: 'Nicht hilfreich',
|
||||
submit: 'Absenden',
|
||||
annotation_button_label: 'Kommentar öffnen',
|
||||
code_copied: 'Kopiert!',
|
||||
|
||||
@@ -32,6 +32,8 @@ export const en = {
|
||||
was_this_helpful_negative: 'No',
|
||||
was_this_helpful_thank_you: 'Thank you!',
|
||||
was_this_helpful_comment: "Anything you'd like to add?",
|
||||
was_this_helpful_positive_label: 'Helpful',
|
||||
was_this_helpful_negative_label: 'Not helpful',
|
||||
submit: 'Submit',
|
||||
annotation_button_label: 'Open annotation',
|
||||
code_copied: 'Copied!',
|
||||
|
||||
@@ -34,6 +34,8 @@ export const es: TranslationLanguage = {
|
||||
was_this_helpful_negative: 'No',
|
||||
was_this_helpful_thank_you: '¡Gracias!',
|
||||
was_this_helpful_comment: '¿Algo más que te gustaría añadir?',
|
||||
was_this_helpful_positive_label: 'Útil',
|
||||
was_this_helpful_negative_label: 'No útil',
|
||||
submit: 'Enviar',
|
||||
annotation_button_label: 'Abrir anotación',
|
||||
code_copied: '¡Copiado!',
|
||||
|
||||
@@ -34,6 +34,8 @@ export const fr: TranslationLanguage = {
|
||||
was_this_helpful_negative: 'Non',
|
||||
was_this_helpful_thank_you: 'Merci!',
|
||||
was_this_helpful_comment: 'Quelque chose à ajouter?',
|
||||
was_this_helpful_positive_label: 'Utile',
|
||||
was_this_helpful_negative_label: 'Pas utile',
|
||||
submit: 'Soumettre',
|
||||
annotation_button_label: "Ouvrir l'annotation",
|
||||
code_copied: 'Copié !',
|
||||
|
||||
@@ -34,6 +34,8 @@ export const ja: TranslationLanguage = {
|
||||
was_this_helpful_negative: 'いいえ',
|
||||
was_this_helpful_thank_you: 'ありがとうございます!',
|
||||
was_this_helpful_comment: '何か追加したいことはありますか?',
|
||||
was_this_helpful_positive_label: '役立つ',
|
||||
was_this_helpful_negative_label: '役立たない',
|
||||
submit: '送信',
|
||||
annotation_button_label: '注釈を開く',
|
||||
code_copied: 'コピーしました!',
|
||||
|
||||
@@ -34,6 +34,8 @@ export const nl: TranslationLanguage = {
|
||||
was_this_helpful_negative: 'Nee',
|
||||
was_this_helpful_thank_you: 'Bedankt!',
|
||||
was_this_helpful_comment: 'Nog iets toe te voegen?',
|
||||
was_this_helpful_positive_label: 'Nuttig',
|
||||
was_this_helpful_negative_label: 'Niet nuttig',
|
||||
submit: 'Versturen',
|
||||
annotation_button_label: 'Open annotatie',
|
||||
code_copied: 'Gekopieerd!',
|
||||
|
||||
@@ -34,6 +34,8 @@ export const no: TranslationLanguage = {
|
||||
was_this_helpful_negative: 'Nei',
|
||||
was_this_helpful_thank_you: 'Takk!',
|
||||
was_this_helpful_comment: 'Noe du vil legge til?',
|
||||
was_this_helpful_positive_label: 'Nyttig',
|
||||
was_this_helpful_negative_label: 'Ikke nyttig',
|
||||
submit: 'Send inn',
|
||||
annotation_button_label: 'Åpne merknad',
|
||||
code_copied: 'Kopiert!',
|
||||
|
||||
@@ -32,6 +32,8 @@ export const pt_br = {
|
||||
was_this_helpful_negative: 'Não',
|
||||
was_this_helpful_thank_you: 'Obrigado!',
|
||||
was_this_helpful_comment: 'Gostaria de adicionar algo?',
|
||||
was_this_helpful_positive_label: 'Útil',
|
||||
was_this_helpful_negative_label: 'Não útil',
|
||||
submit: 'Enviar',
|
||||
annotation_button_label: 'Abrir anotação',
|
||||
code_copied: 'Copiado!',
|
||||
|
||||
@@ -33,6 +33,8 @@ export const zh: TranslationLanguage = {
|
||||
was_this_helpful_negative: '不',
|
||||
was_this_helpful_thank_you: '谢谢!',
|
||||
was_this_helpful_comment: '您有什么想补充的吗?',
|
||||
was_this_helpful_positive_label: '有帮助',
|
||||
was_this_helpful_negative_label: '没有帮助',
|
||||
submit: '提交',
|
||||
annotation_button_label: '打开批注',
|
||||
code_copied: '已复制!',
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { describe, expect, it } from 'bun:test';
|
||||
import type { RevisionPage } from '@gitbook/api';
|
||||
import {
|
||||
type RevisionPage,
|
||||
RevisionPageLayoutOptionsCoverSize,
|
||||
RevisionPageLayoutOptionsWidth,
|
||||
} from '@gitbook/api';
|
||||
|
||||
import { resolveFirstDocument, resolvePagePath, resolvePagePathDocumentOrGroup } from './pages';
|
||||
|
||||
@@ -28,11 +32,14 @@ describe('resolveFirstDocument', () => {
|
||||
pages: [],
|
||||
layout: {
|
||||
cover: true,
|
||||
coverSize: RevisionPageLayoutOptionsCoverSize.Full,
|
||||
title: true,
|
||||
description: true,
|
||||
tableOfContents: true,
|
||||
outline: true,
|
||||
pagination: true,
|
||||
width: RevisionPageLayoutOptionsWidth.Default,
|
||||
metadata: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -75,11 +82,14 @@ describe('resolveFirstDocument', () => {
|
||||
pages: [],
|
||||
layout: {
|
||||
cover: true,
|
||||
coverSize: RevisionPageLayoutOptionsCoverSize.Full,
|
||||
title: true,
|
||||
description: true,
|
||||
tableOfContents: true,
|
||||
outline: true,
|
||||
pagination: true,
|
||||
width: RevisionPageLayoutOptionsWidth.Default,
|
||||
metadata: true,
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -115,11 +125,14 @@ describe('resolvePagePath', () => {
|
||||
pages: [],
|
||||
layout: {
|
||||
cover: true,
|
||||
coverSize: RevisionPageLayoutOptionsCoverSize.Full,
|
||||
title: true,
|
||||
description: true,
|
||||
tableOfContents: true,
|
||||
outline: true,
|
||||
pagination: true,
|
||||
width: RevisionPageLayoutOptionsWidth.Default,
|
||||
metadata: true,
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -185,11 +198,14 @@ describe('resolvePagePath', () => {
|
||||
pages: [],
|
||||
layout: {
|
||||
cover: true,
|
||||
coverSize: RevisionPageLayoutOptionsCoverSize.Full,
|
||||
title: true,
|
||||
description: true,
|
||||
tableOfContents: true,
|
||||
outline: true,
|
||||
pagination: true,
|
||||
width: RevisionPageLayoutOptionsWidth.Default,
|
||||
metadata: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -49,10 +49,6 @@ export function defaultCustomization(): api.SiteCustomizationSettings {
|
||||
feedback: {
|
||||
enabled: false,
|
||||
},
|
||||
// TODO: remove aiSearch once the cache has been fully updated (after 11/07/2025)
|
||||
aiSearch: {
|
||||
enabled: true,
|
||||
},
|
||||
ai: {
|
||||
mode: api.CustomizationAIMode.None,
|
||||
},
|
||||
@@ -68,6 +64,10 @@ export function defaultCustomization(): api.SiteCustomizationSettings {
|
||||
pagination: {
|
||||
enabled: true,
|
||||
},
|
||||
pageActions: {
|
||||
externalAI: true,
|
||||
markdown: true,
|
||||
},
|
||||
trademark: {
|
||||
enabled: true,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user