diff --git a/bun.lock b/bun.lock index 50099ab0e7..008f621c87 100644 --- a/bun.lock +++ b/bun.lock @@ -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", @@ -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"], diff --git a/package.json b/package.json index 2baf43e0ef..721d953e18 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/packages/gitbook/src/components/DocumentView/CodeBlock/ClientCodeBlock.tsx b/packages/gitbook/src/components/DocumentView/CodeBlock/ClientCodeBlock.tsx index 9d8cfbb399..9280a0c27b 100644 --- a/packages/gitbook/src/components/DocumentView/CodeBlock/ClientCodeBlock.tsx +++ b/packages/gitbook/src/components/DocumentView/CodeBlock/ClientCodeBlock.tsx @@ -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'; @@ -18,6 +21,8 @@ type ClientBlockProps = Pick, '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. @@ -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 = ( ); + + return isExpandable ? ( + + {renderer} + + ) : ( + 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 ( +
+
+ {children} +
+
+ +
+
+ ); } diff --git a/packages/gitbook/src/components/DocumentView/CodeBlock/CodeBlock.tsx b/packages/gitbook/src/components/DocumentView/CodeBlock/CodeBlock.tsx index 206cb82adb..43e6f7efbe 100644 --- a/packages/gitbook/src/components/DocumentView/CodeBlock/CodeBlock.tsx +++ b/packages/gitbook/src/components/DocumentView/CodeBlock/CodeBlock.tsx @@ -50,7 +50,7 @@ export async function CodeBlock(props: BlockProps) { 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 ; diff --git a/packages/gitbook/src/components/DocumentView/CodeBlock/CodeBlockRenderer.tsx b/packages/gitbook/src/components/DocumentView/CodeBlock/CodeBlockRenderer.tsx index a3935ce9c7..e50e874eb8 100644 --- a/packages/gitbook/src/components/DocumentView/CodeBlock/CodeBlockRenderer.tsx +++ b/packages/gitbook/src/components/DocumentView/CodeBlock/CodeBlockRenderer.tsx @@ -12,6 +12,7 @@ import type { HighlightLine, HighlightToken } from './highlight'; type CodeBlockRendererProps = Pick, 'block' | 'style'> & { lines: HighlightLine[]; 'aria-busy'?: boolean; + id?: string; }; /** @@ -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 (
                 ) {
     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 (
diff --git a/packages/gitbook/src/intl/translations/de.ts b/packages/gitbook/src/intl/translations/de.ts
index 45de13837f..8c9b407276 100644
--- a/packages/gitbook/src/intl/translations/de.ts
+++ b/packages/gitbook/src/intl/translations/de.ts
@@ -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:
diff --git a/packages/gitbook/src/intl/translations/en.ts b/packages/gitbook/src/intl/translations/en.ts
index 88192135d9..a726ceb14b 100644
--- a/packages/gitbook/src/intl/translations/en.ts
+++ b/packages/gitbook/src/intl/translations/en.ts
@@ -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:
diff --git a/packages/gitbook/src/intl/translations/es.ts b/packages/gitbook/src/intl/translations/es.ts
index 36273080b6..e9f1088c2d 100644
--- a/packages/gitbook/src/intl/translations/es.ts
+++ b/packages/gitbook/src/intl/translations/es.ts
@@ -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:
diff --git a/packages/gitbook/src/intl/translations/fr.ts b/packages/gitbook/src/intl/translations/fr.ts
index 98fc2c11e6..f038e3eece 100644
--- a/packages/gitbook/src/intl/translations/fr.ts
+++ b/packages/gitbook/src/intl/translations/fr.ts
@@ -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:
diff --git a/packages/gitbook/src/intl/translations/it.ts b/packages/gitbook/src/intl/translations/it.ts
index b87a05651c..232a8c24d4 100644
--- a/packages/gitbook/src/intl/translations/it.ts
+++ b/packages/gitbook/src/intl/translations/it.ts
@@ -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:
diff --git a/packages/gitbook/src/intl/translations/ja.ts b/packages/gitbook/src/intl/translations/ja.ts
index 49d20c19be..d100c7f44a 100644
--- a/packages/gitbook/src/intl/translations/ja.ts
+++ b/packages/gitbook/src/intl/translations/ja.ts
@@ -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:
diff --git a/packages/gitbook/src/intl/translations/nl.ts b/packages/gitbook/src/intl/translations/nl.ts
index db6d1ce270..9f8a6ace0e 100644
--- a/packages/gitbook/src/intl/translations/nl.ts
+++ b/packages/gitbook/src/intl/translations/nl.ts
@@ -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:
diff --git a/packages/gitbook/src/intl/translations/no.ts b/packages/gitbook/src/intl/translations/no.ts
index 3fcbdd7219..25884678fb 100644
--- a/packages/gitbook/src/intl/translations/no.ts
+++ b/packages/gitbook/src/intl/translations/no.ts
@@ -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:
diff --git a/packages/gitbook/src/intl/translations/pt-br.ts b/packages/gitbook/src/intl/translations/pt-br.ts
index bfb11826e5..b9d0d3182b 100644
--- a/packages/gitbook/src/intl/translations/pt-br.ts
+++ b/packages/gitbook/src/intl/translations/pt-br.ts
@@ -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:
diff --git a/packages/gitbook/src/intl/translations/ru.ts b/packages/gitbook/src/intl/translations/ru.ts
index d5cb73e4cb..c88e999f6a 100644
--- a/packages/gitbook/src/intl/translations/ru.ts
+++ b/packages/gitbook/src/intl/translations/ru.ts
@@ -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:
diff --git a/packages/gitbook/src/intl/translations/zh.ts b/packages/gitbook/src/intl/translations/zh.ts
index 129ebd4f19..13b2207ecc 100644
--- a/packages/gitbook/src/intl/translations/zh.ts
+++ b/packages/gitbook/src/intl/translations/zh.ts
@@ -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}。',