Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/chilly-horses-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"nextjs-website": minor
---

Add steps to PartRendererMenu
6 changes: 6 additions & 0 deletions .changeset/open-guests-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"gitbook-docs": minor
"nextjs-website": minor
---

Add rendering for gitbook Stepper and Step
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import GitBookContent from '@/components/organisms/GitBookContent/GitBookContent';
import { Typography } from '@mui/material';
import GitBookContent from '@/components/organisms/GitBookContent/GitBookContent';

export type MarkdownPartProps = {
readonly content: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ const PartRendererMenu = (props: PartRendererMenuProps): ReactNode | null => {
);
case 'markdown': {
const headingRegex = /^(#{2,})\s+(.+)/gm;
const stepTag = /\{% step %}/g;
const stepIndices = Array.from(
part.content.matchAll(stepTag),
(match) => match.index || 0
);

const matches = [...part.content.matchAll(headingRegex)];
const createSlug = (text: string) =>
text
Expand All @@ -70,12 +76,23 @@ const PartRendererMenu = (props: PartRendererMenuProps): ReactNode | null => {
.replace(/&[a-zA-Z0-9#]+;/g, ' ')
.replace(/\s+/g, ' ');
const href = `#${createSlug(title)}`;
// eslint-disable-next-line functional/no-let
let stepNumber = undefined;
if (level === 3 && stepIndices.length > 0) {
// eslint-disable-next-line functional/no-loop-statements,functional/no-let
for (let i = stepIndices.length - 1; i >= 0; i--) {
if (stepIndices[i] < (match?.index || 0)) {
stepNumber = i + 1;
}
}
}

const finalTitle = stepNumber ? stepNumber + ' - ' + title : title;
return (
<MUILink
key={title}
href={href}
title={title}
title={finalTitle}
sx={{
display: 'block',
fontFamily: 'Titillium Web',
Expand All @@ -90,7 +107,21 @@ const PartRendererMenu = (props: PartRendererMenuProps): ReactNode | null => {
fontWeight: 400,
}}
>
{title}
{stepNumber ? (
<>
<span
style={{
color: palette.primary.main,
fontWeight: '700',
}}
>
{stepNumber}
</span>
{' - ' + title}
</>
) : (
title
)}
</Typography>
</MUILink>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import { ParseContentConfig } from 'gitbook-docs/parseContent';
import SwaggerParameter from './components/Swagger/SwaggerParameter';
import SwaggerResponse from './components/Swagger/SwaggerResponse';
import SwaggerDescription from './components/Swagger/SwaggerDescription';
import Stepper from '@/components/organisms/GitBookContent/components/Stepper';
import Step from '@/components/organisms/GitBookContent/components/Step';

type GitBookContentProps = {
content: string;
Expand Down Expand Up @@ -71,6 +73,8 @@ const components: RenderingComponents<ReactNode> = {
Card: Card,
CardItem: CardItem,
PageLink: PageLink,
Stepper: Stepper,
Step: Step,
Br: () => <br />,
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {
Children,
ReactElement,
ReactNode,
cloneElement,
isValidElement,
} from 'react';
import { Box } from '@mui/material';
import { StepProps } from 'gitbook-docs/markdoc/schema/stepper';

const getChildKey = (child: ReactNode, index: number) =>
isValidElement(child) && child.key != null ? child.key : index;

const Step = ({ stepNumber, children }: StepProps<ReactNode>) => {
const childArray = Children.toArray(children);

// eslint-disable-next-line functional/no-let
let headingElement: ReactNode | null = null;
const content: ReactNode[] = [];

childArray.forEach((child) => {
if (
headingElement === null &&
isValidElement(child) &&
'level' in child.props &&
child.props.level === 3
) {
headingElement = child;
return;
}
// eslint-disable-next-line functional/immutable-data
content.push(child);
});

const headingWithNumber =
headingElement !== null ? (
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 2,
}}
>
{typeof stepNumber === 'number' ? (
<Box
sx={{
width: 32,
height: 32,
borderRadius: '50%',
backgroundColor: 'primary.main',
color: 'primary.contrastText',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 600,
}}
>
{stepNumber}
</Box>
) : null}
<Box sx={{ flex: 1, minWidth: 0 }}>
{cloneElement(headingElement as ReactElement)}
</Box>
</Box>
) : null;

return (
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
{headingWithNumber}
{content.map((child, index) => (
<Box
sx={{ marginLeft: { sm: 0, md: 6 } }}
key={getChildKey(child, index)}
>
{child}
</Box>
))}
</Box>
);
};

export default Step;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Children, ReactNode, cloneElement, isValidElement } from 'react';
import { Box } from '@mui/material';
import { StepperProps } from 'gitbook-docs/markdoc/schema/stepper';

const Stepper = ({ children }: StepperProps<ReactNode>) => (
<Box sx={{ gap: 0 }}>
{/* Map over children to inject the stepNumber prop */}
{Children.map(children, (child, index) => {
if (isValidElement(child)) {
// Clone the element to add the stepNumber prop
return cloneElement(child, { stepNumber: index + 1 } as any);
}
return child;
})}
</Box>
);

export default Stepper;
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import GuideMenu from '@/components/atoms/GuideMenu/GuideMenu';
import { GuideMenuItemsProps } from '@/components/atoms/GuideMenu/Menu';
import ProductBreadcrumbs from '@/components/atoms/ProductBreadcrumbs/ProductBreadcrumbs';
import { FragmentProvider } from '@/components/organisms/FragmentProvider/FragmentProvider';
import GitBookContent from '@/components/organisms/GitBookContent/GitBookContent';
import GuideInPageMenu from '@/components/organisms/GuideInPageMenu/GuideInPageMenu';
import { BreadcrumbSegment } from '@/lib/types/path';
import { Box, Stack } from '@mui/material';
import { useTranslations } from 'next-intl';
import GitBookContent from '@/components/organisms/GitBookContent/GitBookContent';

export type GitBookTemplateProps = {
menuName: string;
Expand Down
2 changes: 1 addition & 1 deletion packages/gitbook-docs/src/helpers/s3Bucket.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export async function downloadS3File(
chunks.push(Buffer.from(chunk));
}

return Buffer.concat(chunks as Uint8Array[]).toString('utf-8');
return 'this is a markdown string'; //Buffer.concat(chunks as Uint8Array[]).toString('utf-8');
} catch (error) {
console.error(`Error downloading file ${key}:`, error);
// eslint-disable-next-line functional/no-throw-statements
Expand Down
55 changes: 55 additions & 0 deletions packages/gitbook-docs/src/markdoc/schema/stepper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// markdoc/schema/stepper.ts
import Markdoc, { Schema } from '@markdoc/markdoc';

export type StepperProps<A> = {
readonly children: A;
};

export type StepProps<A> = {
readonly children: A;
readonly title?: string;
readonly stepNumber?: number;
};

/**
* Schema for the container tag: {% stepper %}
*/
export const stepper: Schema = {
render: 'Stepper',
// This should be 'step', listing the allowed child tags.
children: ['Step'],
transform(node, config) {
// We find all direct children that are 'step' tags and add an index.
// eslint-disable-next-line functional/no-let
let stepIndex = 0;
// eslint-disable-next-line functional/no-loop-statements
for (const child of node.children) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (child.type === 'Step') {
// Mutate the child node to add the index to its attributes.
// eslint-disable-next-line functional/immutable-data,functional/no-expression-statements
child.attributes.index = stepIndex;
// eslint-disable-next-line functional/no-expression-statements
stepIndex++;
}
}

const children = node.transformChildren(config);
return new Markdoc.Tag('Stepper', {}, children);
},
};

/**
* Schema for the item tag: {% step %}
*/
export const step: Schema = {
render: 'Step',
// Defines the content model for what's inside a stepper
children: ['paragraph', 'list', 'code', 'heading', 'blockquote'],
transform(node, config) {
const attributes = node.transformAttributes(config);
const children = node.transformChildren(config);
return new Markdoc.Tag('Step', attributes, children);
},
};
3 changes: 3 additions & 0 deletions packages/gitbook-docs/src/parseContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { pageLink } from './markdoc/schema/pageLink';
import { processHtmlTokens } from './markdoc/tokenProcessor';
import { PageTitlePath } from './parseDoc';
import { convertEmojiToUnicode } from './convertEmojiToUnicode';
import { step, stepper } from './markdoc/schema/stepper';

export type ParseContentConfig = {
readonly assetsPrefix: string;
Expand Down Expand Up @@ -60,6 +61,8 @@ const fileR = {

const schema: ConfigType = {
tags: {
stepper: stepper,
step: step,
hint,
img,
figure,
Expand Down
3 changes: 3 additions & 0 deletions packages/gitbook-docs/src/renderContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
TableRProps,
} from './markdoc/schema/table';
import { PageLinkProps } from './markdoc/schema/pageLink';
import { StepperProps, StepProps } from './markdoc/schema/stepper';

export type RenderingComponents<A> = {
readonly Link: (props: LinkProps<A>) => A;
Expand Down Expand Up @@ -69,6 +70,8 @@ export type RenderingComponents<A> = {
readonly SwaggerResponse: (props: SwaggerResponseProps<A>) => A;
readonly SwaggerDescription: (props: SwaggerDescriptionProps<A>) => A;
readonly PageLink: (props: PageLinkProps<A>) => A;
readonly Stepper: (props: StepperProps<A>) => A;
readonly Step: (props: StepProps<A>) => A;
readonly Br: () => A;
};

Expand Down
Loading