React 및 Puppeteer: PDF 생성(pdf-doc 보기 생성)

23784 단어 nxpdfpuppeteerreact
pdf를 렌더링하는 서비스를 만들기 전에 먼저 pdf 보기가 필요합니다.

목표


  • 서식 있는 텍스트 콘텐츠를 렌더링하는 기능
  • SVG 구성 요소 렌더링
  • 이미지 렌더링
  • 레이아웃 스타일 지정(열 등)을 사용하여 내용 렌더링
  • 사용자 정의 글꼴 지정

  • 이러한 목표를 달성하기 위해 이전 기사에서 몇 가지 라이브러리를 설치했습니다.

    이것들은:
  • 차크라 ui
  • 짜다

  • 보기 만들기



    1 단계



    먼저 서식 있는 텍스트 콘텐츠를 표시하는 데 재사용할 수 있는 서식 있는 텍스트 구성 요소를 만듭니다. 실험을 위해 필요한 유일한 특수 구성 요소입니다. 다른 모든 유용한 구성 요소는 chakra ui에서 제공됩니다.

    // file: libs/pdf-doc/src/lib/components/rich-text.tsx
    
    import { Box, BoxProps } from '@chakra-ui/react';
    import { Markup } from 'interweave';
    
    interface RichTextProps extends BoxProps {
      content: string;
    }
    
    export const RichText = ({ content, ...props }: RichTextProps) => {
      return (
        <Box
          {...props}
          sx={{
            p: {
              fontSize: '12px',
              marginBottom: '8px',
            },
            li: {
              fontSize: '12px',
              paddingLeft: '16px',
            },
            ol: {
              paddingInlineStart: '20px',
              mb: '20px',
            },
            ul: {
              paddingInlineStart: '20px',
              mb: '20px',
            },
          }}
        >
          <Markup content={content} />
        </Box>
      );
    };
    


    2 단계



    템플릿에 대한 몇 가지 샘플 데이터 및 유형을 생성해 보겠습니다.

    참고: 데이터가 잘립니다. 전체 예제는 저장소를 참조하십시오.

    // file: libs/constants/src/lib/constants.ts
    
    export const samplePdfData = {
      images: [
       // this is playful, images will be different per render
    'https://source.unsplash.com/category/technology/1600x900',
        'https://source.unsplash.com/category/nature/1600x900',
        'https://source.unsplash.com/category/sports/1600x900',
        'https://source.unsplash.com/category/bike/1600x900',
        'https://source.unsplash.com/category/dogs/1600x900',
        'https://source.unsplash.com/category/cats/1600x900',
      ].map((image, index) => ({ id: index, url: image })),
      title: 'Some random pdf',
      description:
        '<p>Duis autem vel eum iriure dolor in...</p>...',
    };
    



    // file: libs/constants/src/lib/types.ts
    
    import { PDFOptions } from 'puppeteer';
    
    export interface PDFMetadata {
      title: string;
      subject: string;
      author: string;
      producer: string;
      creator: string;
    }
    
    export interface Font {
      familyDisplay: string;
      family: string;
      fontFaces?: {
        style?: string;
        weight?: number;
        format?: string;
        src: string;
      }[];
    }
    
    export interface PDFData {
      id: string | number;
      metadata: PDFMetadata;
      options?: PDFOptions;
      font: Font;
    }
    
    export interface PDFDocumentData<T> extends PDFData {
      document: T;
    }
    


    참고: 라이브러리에서 두 파일을 모두 내보냈는지 확인하십시오.

    3단계



    관점을 발전시키는 데 도움이 되는 이야기 만들기

    // file: libs/pdf-doc/src/lib/pdf-doc.stories.tsx
    
    // to run the instance:
    // pnpm nx run pdf-doc:storybook 
    
    import { Meta, Story } from '@storybook/react';
    import { samplePdfData } from '@pdf-generation/constants';
    import { PdfDoc, PdfDocProps } from './pdf-doc';
    
    export default {
      component: PdfDoc,
      title: 'Components/PdfDoc',
    } as Meta;
    
    const Template: Story<PdfDocProps> = (args: PdfDocProps) => {
      return <PdfDoc {...args} />;
    };
    
    export const DefaultExample = Template.bind({});
    
    DefaultExample.args = samplePdfData;
    
    


    4단계



    PDF 보기를 만듭니다. 이 부분은 전적으로 귀하에게 달려 있지만 이 실험의 최종 pdf 구성 요소를 참조하십시오.
    또한 자세한 내용은 저장소를 확인하십시오.

    import { Box, Heading, Stack, Text } from '@chakra-ui/react';
    import { CustomSvg } from './components/custom-svg';
    import { Icons } from './components/icons';
    import { Images } from './components/images';
    import { RichText } from './components/rich-text';
    import { SectionTitle } from './components/section-title';
    import { ImageData } from './pdf-doc.types';
    
    export interface PdfDocProps {
      images: ImageData[];
      title: string;
      description: string;
    }
    
    export function PdfDoc(props: PdfDocProps) {
      const { title, description, images } = props;
      return (
        <Stack spacing={6} fontSize="md">
          <Heading as="h1" size="4xl" color="blue.800">
            {title}
          </Heading>
          <Stack spacing={3}>
            <Text>This is normal text</Text>
    
            <Heading as="h3" size="l" color="blue.200">
              Description (rich text)
            </Heading>
            <RichText content={description} />
          </Stack>
    
          <SectionTitle>Images</SectionTitle>
          <Images items={images} />
    
          <SectionTitle>Icons</SectionTitle>
          <Icons />
    
          <SectionTitle>Custom Svg</SectionTitle>
          <Box fontSize="200px">
            <CustomSvg />
          </Box>
        </Stack>
      );
    }
    
    


    5단계



    pdf 보기를 문자열로 렌더링하는 함수를 생성하고 내보낸 것을 확인합니다index.ts.

    // file: libs/pdf-doc/src/lib/pdf-doc.server.tsx
    
    import { renderToString } from 'react-dom/server';
    import {
      ChakraProvider,
      extendTheme,
      theme as chakraTheme,
    } from '@chakra-ui/react';
    import { Font } from '@pdf-generation/constants';
    import { PdfDoc, PdfDocProps } from './pdf-doc';
    
    export const renderPdfDoc = (data: PdfDocProps, font?: Font) => {
      const fontFamilyDisplay =
        font?.familyDisplay || font?.family;
    
      return renderToString(
        <ChakraProvider
          theme={extendTheme({
            fonts: {
              ...chakraTheme.fonts,
              body: fontFamilyDisplay || chakraTheme.fonts.body,
              heading: fontFamilyDisplay || chakraTheme.fonts.heading,
            },
          })}
        >
          <PdfDoc {...data} />
        </ChakraProvider>
      );
    };
    



    그게 다야!

    이제 pdf를 생성하기 위한 컨트롤러를 생성합니다.

    좋은 웹페이지 즐겨찾기