diff --git a/packages/oc-docs/e2e/collection-docs.spec.ts b/packages/oc-docs/e2e/collection-docs.spec.ts index 7d858d1..2dbabc1 100644 --- a/packages/oc-docs/e2e/collection-docs.spec.ts +++ b/packages/oc-docs/e2e/collection-docs.spec.ts @@ -19,12 +19,22 @@ test.describe('Collection-level documentation', () => { test('renders markdown headings', async ({ page }) => { const docs = page.locator('.collection-docs'); - await expect(docs.getByRole('heading', { name: 'Bruno Testbench', level: 1 })).toBeVisible(); await expect(docs.getByRole('heading', { name: 'Getting Started', level: 2 })).toBeVisible(); await expect(docs.getByRole('heading', { name: 'Authentication', level: 2 })).toBeVisible(); await expect(docs.getByRole('heading', { name: 'Rate Limits', level: 2 })).toBeVisible(); }); + test('renders collection name as page header above docs', async ({ page }) => { + const heading = page + .locator('.playground-content') + .getByRole('heading', { name: 'Bruno Testbench', level: 1 }); + await expect(heading).toBeVisible(); + + const headingBox = await heading.boundingBox(); + const docsBox = await page.locator('.collection-docs').boundingBox(); + expect(headingBox!.y).toBeLessThan(docsBox!.y); + }); + test('renders markdown paragraphs with inline formatting', async ({ page }) => { const docs = page.locator('.collection-docs'); await expect(docs.getByText('comprehensive API collection for testing')).toBeVisible(); diff --git a/packages/oc-docs/src/components/Docs/Docs.tsx b/packages/oc-docs/src/components/Docs/Docs.tsx index a1e602c..d254c41 100644 --- a/packages/oc-docs/src/components/Docs/Docs.tsx +++ b/packages/oc-docs/src/components/Docs/Docs.tsx @@ -3,10 +3,12 @@ import type { OpenCollection as OpenCollectionCollection } from '@opencollection import type { StructuredText } from '@opencollection/types/common/description'; import Sidebar from './Sidebar/Sidebar'; import Item from './Item/Item'; +import FetchInBrunoButton from './Sidebar/FetchInBrunoButton'; import { getItemId, generateSafeId } from '../../utils/itemUtils'; import { isFolder } from '../../utils/schemaHelpers'; import { useAppSelector, useAppDispatch } from '../../store/hooks'; import { selectSelectedItemId, selectItem } from '../../store/slices/docs'; +import { selectGitCollectionUrl } from '../../store/slices/app'; import { useMarkdownRenderer } from '../../hooks'; interface DocsProps { @@ -22,6 +24,7 @@ const Docs: React.FC = ({ }) => { const dispatch = useAppDispatch(); const selectedItemId = useAppSelector(selectSelectedItemId); + const gitCollectionUrl = useAppSelector(selectGitCollectionUrl); const md = useMarkdownRenderer(); const isInitialMount = useRef(true); @@ -112,6 +115,28 @@ const Docs: React.FC = ({ className="playground-content h-full overflow-y-auto flex-1" >
+ {docsCollection?.info?.name && ( +
+

+ {docsCollection.info.name} +

+ {gitCollectionUrl && ( + + + + )} +
+ )} + {/* Collection-level documentation/introduction */} {docsCollection?.docs && (
( + + + + + + + + + + + + + + + + + + + + + + + + Fetch In Bruno + +); + +export default FetchInBrunoButton; diff --git a/packages/oc-docs/src/components/Docs/Sidebar/Sidebar.tsx b/packages/oc-docs/src/components/Docs/Sidebar/Sidebar.tsx index 029a3e7..be53f33 100644 --- a/packages/oc-docs/src/components/Docs/Sidebar/Sidebar.tsx +++ b/packages/oc-docs/src/components/Docs/Sidebar/Sidebar.tsx @@ -124,7 +124,7 @@ const Sidebar: React.FC = () => { {/* Collection name at top */}
-
+

{collection?.info?.name || 'API Collection'}

diff --git a/packages/oc-docs/src/components/OpenCollection/OpenCollection.tsx b/packages/oc-docs/src/components/OpenCollection/OpenCollection.tsx index 241cd19..258420a 100644 --- a/packages/oc-docs/src/components/OpenCollection/OpenCollection.tsx +++ b/packages/oc-docs/src/components/OpenCollection/OpenCollection.tsx @@ -27,7 +27,8 @@ import { setCollectionLoading, setCollectionSucceeded, setCollectionFailed, - resetCollectionState + resetCollectionState, + setGitCollectionUrl } from '@slices/app'; import { createOpenCollectionStore, type AppStore } from '../../store/store'; @@ -162,10 +163,12 @@ const DesktopLayout: React.FC = ({ export interface OpenCollectionProps { collection: IOpenCollection | string | File; logo?: React.ReactNode; + gitCollectionUrl?: string; } const OpenCollectionContent: React.FC = ({ collection, + gitCollectionUrl, }) => { const dispatch = useAppDispatch(); const docsCollection = useAppSelector(selectDocsCollection); @@ -174,6 +177,10 @@ const OpenCollectionContent: React.FC = ({ const collectionError = useAppSelector(selectCollectionError); const selectedItemId = useAppSelector((state) => state.docs.selectedItemId); + useEffect(() => { + gitCollectionUrl && dispatch(setGitCollectionUrl(gitCollectionUrl)); + }, [gitCollectionUrl, dispatch]); + useEffect(() => { let isActive = true; diff --git a/packages/oc-docs/src/dev.tsx b/packages/oc-docs/src/dev.tsx index 3a06af2..0e7bf68 100644 --- a/packages/oc-docs/src/dev.tsx +++ b/packages/oc-docs/src/dev.tsx @@ -31,6 +31,7 @@ const DevApp: React.FC = () => {
diff --git a/packages/oc-docs/src/sampleCollection.ts b/packages/oc-docs/src/sampleCollection.ts index 0aead7d..3c4f065 100644 --- a/packages/oc-docs/src/sampleCollection.ts +++ b/packages/oc-docs/src/sampleCollection.ts @@ -32,8 +32,6 @@ request: token: "{{bearer_auth_token}}" docs: content: | - # Bruno Testbench - This is a comprehensive API collection for testing **OpenCollection** features. ## Getting Started diff --git a/packages/oc-docs/src/standalone.ts b/packages/oc-docs/src/standalone.ts index 0cb0a0b..02b4574 100644 --- a/packages/oc-docs/src/standalone.ts +++ b/packages/oc-docs/src/standalone.ts @@ -23,6 +23,7 @@ export interface OpenCollectionOptions { target: HTMLElement; opencollection: any; logo?: string; + gitCollectionUrl?: string; } export class OpenCollectionRenderer { @@ -96,7 +97,8 @@ export class OpenCollectionRenderer { this.root.render(React.createElement(OpenCollection, { collection, - logo: this.createLogoElement() + logo: this.createLogoElement(), + gitCollectionUrl: this.options.gitCollectionUrl })); } diff --git a/packages/oc-docs/src/store/slices/app.ts b/packages/oc-docs/src/store/slices/app.ts index cd36008..fbc2d04 100644 --- a/packages/oc-docs/src/store/slices/app.ts +++ b/packages/oc-docs/src/store/slices/app.ts @@ -6,11 +6,13 @@ export type CollectionStatus = 'idle' | 'loading' | 'succeeded' | 'failed'; export interface AppState { collectionStatus: CollectionStatus; collectionError: string | null; + gitCollectionUrl: string | null; } const initialState: AppState = { collectionStatus: 'idle', - collectionError: null + collectionError: null, + gitCollectionUrl: null }; const appSlice = createSlice({ @@ -32,6 +34,9 @@ const appSlice = createSlice({ resetCollectionState: (state: AppState) => { state.collectionStatus = 'idle'; state.collectionError = null; + }, + setGitCollectionUrl: (state: AppState, action: PayloadAction) => { + state.gitCollectionUrl = action.payload; } } }); @@ -40,11 +45,13 @@ export const { setCollectionLoading, setCollectionSucceeded, setCollectionFailed, - resetCollectionState + resetCollectionState, + setGitCollectionUrl } = appSlice.actions; export default appSlice.reducer; export const selectCollectionStatus = (state: RootState) => state.app.collectionStatus; export const selectCollectionError = (state: RootState) => state.app.collectionError; +export const selectGitCollectionUrl = (state: RootState) => state.app.gitCollectionUrl;