mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-24 03:16:40 +00:00
Add basic support for computed pages types (#2520)
This commit is contained in:
+1
-1
@@ -8,7 +8,7 @@
|
||||
},
|
||||
"packageManager": "bun@1.1.18",
|
||||
"patchedDependencies": {
|
||||
"@vercel/next@4.3.6": "patches/@vercel%2Fnext@4.3.6.patch"
|
||||
"@vercel/next@4.3.15": "patches/@vercel%2Fnext@4.3.15.patch"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"clean": "rm -rf ./.next && rm -rf ./public/~gitbook/static"
|
||||
},
|
||||
"dependencies": {
|
||||
"@gitbook/api": "0.64.1",
|
||||
"@gitbook/api": "^0.66.0",
|
||||
"@gitbook/cache-do": "workspace:*",
|
||||
"@gitbook/emoji-codepoints": "workspace:*",
|
||||
"@gitbook/icons": "workspace:*",
|
||||
@@ -41,7 +41,7 @@
|
||||
"katex": "^0.16.9",
|
||||
"mathjax": "^3.2.2",
|
||||
"memoizee": "^0.4.15",
|
||||
"next": "^14.2.5",
|
||||
"next": "14.2.15",
|
||||
"next-themes": "^0.2.1",
|
||||
"nuqs": "^1.17.4",
|
||||
"object-hash": "^3.0.0",
|
||||
|
||||
@@ -84,10 +84,12 @@ function flattenPages(
|
||||
return [
|
||||
...(page.type === 'document' ? [{ page, depth }] : []),
|
||||
...page.pages.flatMap((child) =>
|
||||
child.type === 'link' ? [] : flattenPage(child, depth + 1),
|
||||
child.type === 'document' ? flattenPage(child, depth + 1) : [],
|
||||
),
|
||||
];
|
||||
};
|
||||
|
||||
return rootPags.flatMap((page) => (page.type === 'link' ? [] : flattenPage(page, 0)));
|
||||
return rootPags.flatMap((page) =>
|
||||
page.type === 'group' || page.type === 'document' ? flattenPage(page, 0) : [],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -315,7 +315,7 @@ function selectPages(
|
||||
return [
|
||||
{ page, depth },
|
||||
...page.pages.flatMap((child) => {
|
||||
if (child.type === 'link') {
|
||||
if (child.type !== 'document') {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ function selectPages(
|
||||
}
|
||||
|
||||
const allPages = rootPages.flatMap((page) => {
|
||||
if (page.type === 'link') {
|
||||
if (page.type !== 'document' && page.type !== 'group') {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ export async function IntegrationBlock(props: BlockProps<DocumentBlockIntegratio
|
||||
renderIntegrationUi(block.data.integration, initialInput),
|
||||
true,
|
||||
);
|
||||
if (!initialOutput) {
|
||||
if (!initialOutput || initialOutput.type === 'complete') {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@ export async function PageBodyBlankslate(props: {
|
||||
}) {
|
||||
const { page, rootPages, context } = props;
|
||||
|
||||
const pages = page.pages.filter((child) => (child.type === 'document' ? !child.hidden : true));
|
||||
const pages = page.pages.filter((child) =>
|
||||
child.type === RevisionPageType.Document ? !child.hidden : true,
|
||||
);
|
||||
if (!pages.length) {
|
||||
return null;
|
||||
}
|
||||
@@ -43,7 +45,11 @@ export async function PageBodyBlankslate(props: {
|
||||
/>
|
||||
);
|
||||
|
||||
if (child.type === RevisionPageType.Link) {
|
||||
if (child.type === RevisionPageType.Computed) {
|
||||
throw new Error(
|
||||
'Unexpected computed page, it should have been computed in the API',
|
||||
);
|
||||
} else if (child.type === RevisionPageType.Link) {
|
||||
const resolved = await resolveContentRef(child.target, context);
|
||||
if (!resolved) {
|
||||
return null;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { RevisionPage, RevisionPageDocument, RevisionPageGroup } from '@gitbook/api';
|
||||
import {
|
||||
RevisionPage,
|
||||
RevisionPageDocument,
|
||||
RevisionPageGroup,
|
||||
RevisionPageType,
|
||||
} from '@gitbook/api';
|
||||
|
||||
import { ContentRefContext } from '@/lib/references';
|
||||
import { ClassValue, tcls } from '@/lib/tailwind';
|
||||
@@ -19,7 +24,13 @@ export function PagesList(props: {
|
||||
return (
|
||||
<ul className={tcls('flex', 'flex-1', 'flex-col', 'gap-y-0.5', style)}>
|
||||
{pages.map((page) => {
|
||||
if (page.type === 'link') {
|
||||
if (page.type === RevisionPageType.Computed) {
|
||||
throw new Error(
|
||||
'Unexpected computed page, it should have been computed in the API',
|
||||
);
|
||||
}
|
||||
|
||||
if (page.type === RevisionPageType.Link) {
|
||||
return <PageLinkItem key={page.id} page={page} context={context} />;
|
||||
}
|
||||
|
||||
@@ -27,7 +38,7 @@ export function PagesList(props: {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (page.type === 'group') {
|
||||
if (page.type === RevisionPageType.Group) {
|
||||
return (
|
||||
<PageGroupItem
|
||||
key={page.id}
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import { Revision, RevisionPage, RevisionPageDocument, RevisionPageGroup } from '@gitbook/api';
|
||||
import {
|
||||
Revision,
|
||||
RevisionPage,
|
||||
RevisionPageDocument,
|
||||
RevisionPageGroup,
|
||||
RevisionPageType,
|
||||
} from '@gitbook/api';
|
||||
|
||||
export type AncestorRevisionPage = RevisionPageDocument | RevisionPageGroup;
|
||||
|
||||
@@ -14,7 +20,7 @@ export function resolvePagePath(
|
||||
ancestors: AncestorRevisionPage[],
|
||||
): { page: RevisionPageDocument; ancestors: AncestorRevisionPage[] } | undefined => {
|
||||
for (const page of pages) {
|
||||
if (page.type === 'link') {
|
||||
if (page.type === RevisionPageType.Link || page.type === RevisionPageType.Computed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -56,7 +62,7 @@ export function resolvePageId(
|
||||
ancestors: AncestorRevisionPage[],
|
||||
): { page: RevisionPageDocument; ancestors: AncestorRevisionPage[] } | undefined => {
|
||||
for (const page of pages) {
|
||||
if (page.type === 'link') {
|
||||
if (page.type === RevisionPageType.Link || page.type === RevisionPageType.Computed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -139,14 +145,14 @@ function resolvePageDocument(
|
||||
page: RevisionPage,
|
||||
ancestors: AncestorRevisionPage[],
|
||||
): { page: RevisionPageDocument; ancestors: AncestorRevisionPage[] } | undefined {
|
||||
if (page.type === 'group') {
|
||||
if (page.type === RevisionPageType.Group) {
|
||||
const firstDocument = resolveFirstDocument(page.pages, [...ancestors, page]);
|
||||
if (firstDocument) {
|
||||
return firstDocument;
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (page.type === 'link') {
|
||||
} else if (page.type === RevisionPageType.Link || page.type === RevisionPageType.Computed) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -162,7 +168,7 @@ function flattenPages(
|
||||
): RevisionPageDocument[] {
|
||||
const result: RevisionPageDocument[] = [];
|
||||
for (const page of pages) {
|
||||
if (page.type === 'link') {
|
||||
if (page.type === RevisionPageType.Link || page.type === RevisionPageType.Computed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -170,7 +176,7 @@ function flattenPages(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (page.type === 'document') {
|
||||
if (page.type === RevisionPageType.Document) {
|
||||
result.push(page);
|
||||
}
|
||||
result.push(...flattenPages(page.pages, filter));
|
||||
|
||||
@@ -35,7 +35,8 @@
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"dev": "tsc -w",
|
||||
"clean": "rm -rf ./dist && rm -rf ./src/data"
|
||||
"clean": "rm -rf ./dist && rm -rf ./src/data",
|
||||
"unit": "bun test"
|
||||
},
|
||||
"bin": {
|
||||
"gitbook-icons": "./bin/gitbook-icons.js"
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { it } from 'bun:test';
|
||||
import { validateIconName } from './icons';
|
||||
|
||||
it('should have the GitBook custom icon', () => {
|
||||
if (!validateIconName('gitbook')) {
|
||||
const message =
|
||||
'The GitBook icon is missing. It indicates that the dependencies were installed without the font-awesome custom package.';
|
||||
if (process.env.CI) {
|
||||
throw new Error(message);
|
||||
} else {
|
||||
console.warn(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -14,7 +14,10 @@
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "react",
|
||||
"incremental": true
|
||||
"incremental": true,
|
||||
"types": [
|
||||
"bun-types" // add Bun global
|
||||
]
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"classnames": "^2.5.1",
|
||||
"@gitbook/api": "0.64.1",
|
||||
"@gitbook/api": "^0.66.0",
|
||||
"assert-never": "^1.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import type {
|
||||
ContentKitAction,
|
||||
ContentKitRenderOutput,
|
||||
ContentKitRenderOutputElement,
|
||||
RequestRenderIntegrationUI,
|
||||
} from '@gitbook/api';
|
||||
import React from 'react';
|
||||
@@ -15,7 +16,7 @@ import {
|
||||
} from './context';
|
||||
import { resolveDynamicBinding } from './dynamic';
|
||||
|
||||
type ContentKitLifecycleMode = ContentKitRenderOutput['element']['type'];
|
||||
type ContentKitLifecycleMode = ContentKitRenderOutputElement['element']['type'];
|
||||
|
||||
/**
|
||||
* Render a ContentKit component.
|
||||
@@ -27,7 +28,7 @@ export function ContentKit(props: {
|
||||
/** Initial input being displayed */
|
||||
initialInput: RequestRenderIntegrationUI;
|
||||
/** Initial output being displayed */
|
||||
initialOutput: ContentKitRenderOutput;
|
||||
initialOutput: ContentKitRenderOutputElement;
|
||||
/** Initial state to display */
|
||||
children?: React.ReactNode;
|
||||
/** Render a new state */
|
||||
@@ -37,6 +38,8 @@ export function ContentKit(props: {
|
||||
}>;
|
||||
/** Callback when an action is triggered */
|
||||
onAction?: (action: ContentKitAction) => void;
|
||||
/** Callback when the flow is completed */
|
||||
onComplete?: (returnValue: any) => void;
|
||||
}) {
|
||||
const {
|
||||
security,
|
||||
@@ -45,6 +48,7 @@ export function ContentKit(props: {
|
||||
children: initialChildren,
|
||||
render,
|
||||
onAction,
|
||||
onComplete,
|
||||
} = props;
|
||||
|
||||
const [current, setCurrent] = React.useState({
|
||||
@@ -61,7 +65,7 @@ export function ContentKit(props: {
|
||||
const [subView, setSubView] = React.useState<null | {
|
||||
mode: ContentKitLifecycleMode;
|
||||
initialInput: RequestRenderIntegrationUI;
|
||||
initialOutput: ContentKitRenderOutput;
|
||||
initialOutput: ContentKitRenderOutputElement;
|
||||
initialChildren: React.ReactNode;
|
||||
}>(null);
|
||||
|
||||
@@ -85,17 +89,22 @@ export function ContentKit(props: {
|
||||
|
||||
console.log('transition to input', newInput);
|
||||
const result = await render(newInput);
|
||||
const output = result.output;
|
||||
|
||||
console.log('and got output', result.output, 'for', newInput);
|
||||
if (output.type === 'complete') {
|
||||
return onComplete?.(output.returnValue);
|
||||
}
|
||||
|
||||
console.log('and got output', output, 'for', newInput);
|
||||
|
||||
setCurrent((prev) => ({
|
||||
input: newInput,
|
||||
children: result.children,
|
||||
output: result.output,
|
||||
output: output,
|
||||
state: prev.state,
|
||||
}));
|
||||
},
|
||||
[setCurrent, current, render],
|
||||
[setCurrent, current, render, onComplete],
|
||||
);
|
||||
|
||||
const renderer = React.useMemo<ContentKitClientContextType>(() => {
|
||||
@@ -131,12 +140,15 @@ export function ContentKit(props: {
|
||||
|
||||
// Prefetch the modal content to show a loading in the button opening the button
|
||||
const result = await render(modalInput);
|
||||
setSubView({
|
||||
mode: 'modal',
|
||||
initialInput: modalInput,
|
||||
initialOutput: result.output,
|
||||
initialChildren: result.children,
|
||||
});
|
||||
|
||||
if (result.output.type === 'element' || !result.output.type) {
|
||||
setSubView({
|
||||
mode: 'modal',
|
||||
initialInput: modalInput,
|
||||
initialOutput: result.output,
|
||||
initialChildren: result.children,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,11 @@ export function ContentKitOutput(props: {
|
||||
output: ContentKitRenderOutput;
|
||||
}) {
|
||||
const { output, context } = props;
|
||||
|
||||
if (output.type === 'complete') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{process.env.NODE_ENV === 'development' ? (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/dist/index.js b/dist/index.js
|
||||
index c5ea5e053c4e6be202914bdd2e0228bc7be8b976..31c24e146fdf50a806f8c1da7eedc1d941270fa9 100644
|
||||
index 1a8c68c0713d41b0239dc8e3895d31437d3bb2e8..f6fec64252c8f1c6225eb37776f6c0d0e2a42c35 100644
|
||||
--- a/dist/index.js
|
||||
+++ b/dist/index.js
|
||||
@@ -10474,7 +10474,7 @@ var import_path = require("path");
|
||||
Reference in New Issue
Block a user