Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bun.lock
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@
"react-dom": "catalog:",
},
"catalog": {
"@gitbook/api": "0.143.2",
"@gitbook/api": "0.145.0",
"@scalar/api-client-react": "^1.3.46",
"@tsconfig/node20": "^20.1.6",
"@tsconfig/strictest": "^2.0.6",
Expand Down Expand Up @@ -724,7 +724,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.143.2", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-ZIQwIgX+artl0o20ftnzeJyM9icwQ6pFeM55AG/lEdeFbMuUGxTfSnZ90+8Aou8l/3ELR3/tOkU2SAvyKc+ATw=="],
"@gitbook/api": ["@gitbook/api@0.145.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-pq+lqUPdvrVstpojs7uOimaNePg16uE1X2Dx7VDulqResmNp/FiV8a1i99vlYHhfhVA/U7i6wAN0iX4zi0/YZA=="],

"@gitbook/browser-types": ["@gitbook/browser-types@workspace:packages/browser-types"],

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"catalog": {
"@tsconfig/strictest": "^2.0.6",
"@tsconfig/node20": "^20.1.6",
"@gitbook/api": "0.143.2",
"@gitbook/api": "0.145.0",
"@scalar/api-client-react": "^1.3.46",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
'use client';

import type { DocumentBlockCode } from '@gitbook/api';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useEffect, useId, useMemo, useRef, useState } from 'react';

import { useAdaptiveVisitor } from '@/components/Adaptive';
import { useInViewportListener } from '@/components/hooks/useInViewportListener';
import { useScrollListener } from '@/components/hooks/useScrollListener';
import { Button } from '@/components/primitives';
import { t, useLanguage } from '@/intl/client';
import { tcls } from '@/lib/tailwind';
import { useDebounceCallback } from 'usehooks-ts';
import type { BlockProps } from '../Block';
import { type InlineExpressionVariables, useEvaluateInlineExpression } from '../InlineExpression';
Expand All @@ -18,6 +21,8 @@ type ClientBlockProps = Pick<BlockProps<DocumentBlockCode>, 'block' | 'style'> &
inlineExprVariables: InlineExpressionVariables;
};

export const CODE_BLOCK_DEFAULT_COLLAPSED_LINE_COUNT = 10;

/**
* Render a code-block client-side by loading the highlighter asynchronously.
* It allows us to defer some load to avoid blocking the rendering of the whole page with block highlighting.
Expand Down Expand Up @@ -113,13 +118,82 @@ export function ClientCodeBlock(props: ClientBlockProps) {
setLines(null);
}, [isInViewport, block, inlines, evaluateInlineExpression]);

return (
const expandable = block.data.expandable;

const numberOfLinesOfCode = lines?.length ?? plainLines.length;
const collapsedLineCount =
block.data.collapsedLineCount || CODE_BLOCK_DEFAULT_COLLAPSED_LINE_COUNT;
const isExpandable = Boolean(expandable && numberOfLinesOfCode > collapsedLineCount);

const codeBlockBodyId = useId();

const renderer = (
<CodeBlockRenderer
ref={blockRef}
aria-busy={highlighting}
block={block}
style={style}
lines={lines ?? plainLines}
id={codeBlockBodyId}
/>
);

return isExpandable ? (
<CodeBlockExpandable
lines={lines ?? plainLines}
controls={codeBlockBodyId}
collapsedLineCount={collapsedLineCount}
>
{renderer}
</CodeBlockExpandable>
) : (
renderer
);
}

function CodeBlockExpandable(props: {
children: React.ReactNode;
lines: HighlightLine[];
collapsedLineCount: number;
controls?: string;
}) {
const { children, controls, lines = [], collapsedLineCount } = props;
const [isExpanded, setIsExpanded] = useState(false);
const language = useLanguage();
return (
<div className="group/codeblock-expandable relative">
<div
className={tcls(
isExpanded
? '[&_pre]:after:opacity-0'
: '[&_pre]:h-[calc(2rem+var(--line-count)*var(--line-height))] [&_pre]:overflow-y-hidden [&_pre]:after:opacity-100',
'[&_pre]:after:pointer-events-none [&_pre]:after:absolute [&_pre]:after:inset-0 [&_pre]:after:z-1 [&_pre]:after:bg-gradient-to-t [&_pre]:after:from-0% [&_pre]:after:from-tint-2 [&_pre]:after:to-70% [&_pre]:after:to-transparent [&_pre]:after:content-[""]'
)}
style={
{
'--line-count': collapsedLineCount,
'--line-height': '1.25rem',
} as React.CSSProperties
}
>
{children}
</div>
<div className="pointer-events-none absolute bottom-0 flex w-full justify-center">
<Button
icon={isExpanded ? 'chevron-up' : 'chevron-down'}
size="xsmall"
variant="blank"
type="button"
onClick={() => setIsExpanded(!isExpanded)}
className="pointer-events-auto z-1 my-2 text-primary text-sm opacity-0 focus:opacity-11 group-hover/codeblock-expandable:opacity-11"
aria-expanded={isExpanded}
aria-controls={controls}
>
{isExpanded
? t(language, 'code_block_expanded')
: t(language, 'code_block_collapsed', lines.length)}
</Button>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export async function CodeBlock(props: BlockProps<DocumentBlockCode>) {
return { inline, body };
});

if (!isEstimatedOffscreen && !hasInlineExpression) {
if (!isEstimatedOffscreen && !hasInlineExpression && !block.data.expandable) {
// In v2, we render the code block server-side
const lines = await highlight(block, richInlines);
return <CodeBlockRenderer block={block} style={style} lines={lines} />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { HighlightLine, HighlightToken } from './highlight';
type CodeBlockRendererProps = Pick<BlockProps<DocumentBlockCode>, 'block' | 'style'> & {
lines: HighlightLine[];
'aria-busy'?: boolean;
id?: string;
};

/**
Expand All @@ -23,11 +24,12 @@ export const CodeBlockRenderer = forwardRef(function CodeBlockRenderer(
) {
const { block, style, lines, 'aria-busy': ariaBusy } = props;

const id = useId();
const withLineNumbers = Boolean(block.data.lineNumbers) && block.nodes.length > 1;
const withWrap = block.data.overflow === 'wrap';
const title = block.data.title;

const id = useId();
const codeId = props.id || id;
return (
<div
ref={ref}
Expand All @@ -42,7 +44,7 @@ export const CodeBlockRenderer = forwardRef(function CodeBlockRenderer(
) : null}
</div>
<CopyCodeButton
codeId={id}
codeId={codeId}
style="z-2 mt-2 mr-2 self-start justify-self-end leading-none opacity-0 backdrop-blur-md [grid-area:2/1] group-hover/codeblock:opacity-11"
/>
<pre
Expand All @@ -53,7 +55,7 @@ export const CodeBlockRenderer = forwardRef(function CodeBlockRenderer(
)}
>
<code
id={id}
id={codeId}
className={tcls(
'inline-grid min-w-full grid-cols-[auto_1fr] [count-reset:line] print:whitespace-pre-wrap',
withWrap && 'whitespace-pre-wrap'
Expand Down
4 changes: 1 addition & 3 deletions packages/gitbook/src/components/DocumentView/InlineIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ import { textColorToStyle } from './utils/colors';
export async function InlineIcon(props: InlineProps<DocumentInlineIcon>) {
const { inline } = props;
const icon = inline.data.icon as IconName;
// @ts-expect-error remove this comment once API is updated
const color = inline.data.color
? // @ts-expect-error remove "as DocumentMarkColor['data']['text']" once API is updated
(inline.data.color as DocumentMarkColor['data']['text'])
? (inline.data.color as DocumentMarkColor['data']['text'])
: undefined;

return (
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export const de = {
annotation_button_label: 'Kommentar öffnen',
code_copied: 'Kopiert!',
code_copy: 'Kopieren',
code_block_collapsed: 'Alle ${1} Zeilen anzeigen',
code_block_expanded: 'Weniger anzeigen',
table_of_contents_button_label: 'Inhaltsverzeichnis öffnen',
cookies_title: 'Cookies',
cookies_prompt:
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export const en = {
annotation_button_label: 'Open annotation',
code_copied: 'Copied!',
code_copy: 'Copy',
code_block_collapsed: 'Show all ${1} lines',
code_block_expanded: 'Show less',
table_of_contents_button_label: 'Open table of contents',
cookies_title: 'Cookies',
cookies_prompt:
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export const es: TranslationLanguage = {
annotation_button_label: 'Abrir anotación',
code_copied: '¡Copiado!',
code_copy: 'Copiar',
code_block_collapsed: 'Mostrar las ${1} líneas',
code_block_expanded: 'Mostrar menos',
table_of_contents_button_label: 'Abrir índice de contenidos',
cookies_title: 'Cookies',
cookies_prompt:
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export const fr = {
annotation_button_label: 'Afficher l’annotation',
code_copied: 'Copié !',
code_copy: 'Copier',
code_block_collapsed: 'Afficher les ${1} lignes',
code_block_expanded: 'Afficher moins',
table_of_contents_button_label: 'Afficher le sommaire',
cookies_title: 'Cookies',
cookies_prompt:
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export const it: TranslationLanguage = {
annotation_button_label: 'Apri annotazione',
code_copied: 'Copiato!',
code_copy: 'Copia',
code_block_collapsed: 'Mostra tutte le ${1} righe',
code_block_expanded: 'Mostra meno',
table_of_contents_button_label: 'Apri indice dei contenuti',
cookies_title: 'Cookie',
cookies_prompt:
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export const ja: TranslationLanguage = {
annotation_button_label: '注釈を開く',
code_copied: 'コピーしました!',
code_copy: 'コピー',
code_block_collapsed: 'すべての${1}行を表示',
code_block_expanded: '折りたたむ',
table_of_contents_button_label: '目次を開く',
cookies_title: 'クッキー',
cookies_prompt:
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export const nl: TranslationLanguage = {
annotation_button_label: 'Open annotatie',
code_copied: 'Gekopieerd!',
code_copy: 'Kopiëren',
code_block_collapsed: 'Toon alle ${1} regels',
code_block_expanded: 'Toon minder',
table_of_contents_button_label: 'Open inhoudsopgave',
cookies_title: 'Cookies',
cookies_prompt:
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/no.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export const no: TranslationLanguage = {
annotation_button_label: 'Åpne merknad',
code_copied: 'Kopiert!',
code_copy: 'Kopier',
code_block_collapsed: 'Vis alle ${1} linjer',
code_block_expanded: 'Vis færre',
table_of_contents_button_label: 'Åpne innholdsfortegnelse',
cookies_title: 'Informasjonskapsler',
cookies_prompt:
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/pt-br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export const pt_br = {
annotation_button_label: 'Abrir anotação',
code_copied: 'Copiado!',
code_copy: 'Copiar',
code_block_collapsed: 'Mostrar todas as ${1} linhas',
code_block_expanded: 'Mostrar menos',
table_of_contents_button_label: 'Abrir o índice',
cookies_title: 'Cookies',
cookies_prompt:
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export const ru = {
annotation_button_label: 'Открыть аннотацию',
code_copied: 'Скопировано!',
code_copy: 'Копировать',
code_block_collapsed: 'Показать все ${1} строк',
code_block_expanded: 'Показать меньше',
table_of_contents_button_label: 'Открыть оглавление',
cookies_title: 'Файлы cookies',
cookies_prompt:
Expand Down
2 changes: 2 additions & 0 deletions packages/gitbook/src/intl/translations/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export const zh: TranslationLanguage = {
annotation_button_label: '打开批注',
code_copied: '已复制!',
code_copy: '复制',
code_block_collapsed: '显示全部 ${1} 行',
code_block_expanded: '收起',
table_of_contents_button_label: '打开目录',
cookies_title: 'Cookies',
cookies_prompt: '本站使用 cookie 来提供服务并分析流量。浏览本站,即表示您接受${1}。',
Expand Down