├── .github └── workflows │ └── release.yaml ├── .gitignore ├── .npmignore ├── LICENSE.md ├── README.md ├── build └── raw.ts ├── docgen ├── base.css ├── buildExample.tsx ├── buildFileMarkdown.ts ├── buildTemplates.tsx ├── index.ts ├── pageBuilder │ └── buildIntroduction.tsx ├── prune.ts ├── renderPreview.tsx ├── types.ts └── utils.ts ├── docs ├── api-reference │ ├── endpoint │ │ ├── create.mdx │ │ ├── delete.mdx │ │ └── get.mdx │ ├── introduction.mdx │ └── openapi.json ├── components │ ├── compile │ │ └── compile.mdx │ ├── css │ │ ├── css.mdx │ │ ├── font.mdx │ │ └── margins.mdx │ ├── footnote │ │ └── footnote.mdx │ ├── latex │ │ └── latex.mdx │ ├── markdown │ │ └── markdown.mdx │ ├── shell │ │ ├── currentpagetop.mdx │ │ ├── floatbottom.mdx │ │ ├── nobreak.mdx │ │ ├── pagebottom.mdx │ │ ├── pagebreak.mdx │ │ └── pagetop.mdx │ ├── signature │ │ └── field.mdx │ ├── tailwind │ │ └── tailwind.mdx │ └── variables │ │ ├── pagenumber.mdx │ │ ├── pagesnumber.mdx │ │ ├── runningh1.mdx │ │ ├── runningh2.mdx │ │ ├── runningh3.mdx │ │ ├── runningh4.mdx │ │ ├── runningh5.mdx │ │ └── runningh6.mdx ├── contributing.mdx ├── development.mdx ├── essentials │ ├── code.mdx │ ├── images.mdx │ ├── markdown.mdx │ ├── navigation.mdx │ ├── reusable-snippets.mdx │ └── settings.mdx ├── favicon.svg ├── getting-started │ └── setup.mdx ├── guides │ ├── fonts.mdx │ ├── images │ │ └── toc.jpg │ ├── page-layout.mdx │ └── references.mdx ├── images │ ├── background.png │ ├── banner-twitter.jpg │ ├── checks-passed.png │ ├── example.png │ ├── hero-dark.svg │ ├── hero-light.svg │ ├── legacy-vs-react-print.avif │ ├── previews │ │ ├── compile-8dbcfb7e │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── compile-f31067dd │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── css-fa74d9a5 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── currentpagetop-2643a477 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── field-8e7a7bcb │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── floatbottom-1c4af231 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── font-0d283416 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── footnote-e49ec577 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── latex-2663e15e │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── latex-c1cd8f84 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── margins-35fa1266 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── markdown-344947c9 │ │ │ ├── document.1.jpg │ │ │ ├── document.2.jpg │ │ │ └── document.pdf │ │ ├── markdown-cdc02780 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── markdown-f4432de3 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── nobreak-ba337df4 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── pagebottom-fd5eaff9 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── pagebreak-bb162ea2 │ │ │ ├── document.1.jpg │ │ │ ├── document.2.jpg │ │ │ └── document.pdf │ │ ├── pagenumber-4d636b47 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── pagenumber-fe8490ef │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── pagesnumber-ba7ca0ce │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── pagetop-53bf6bd2 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── runningh1-230ef375 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── tailwind-1aadcc0c │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── tailwind-b7e447a6 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── tailwind-e99fe796 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── ui-templates-invoice-advanced-657df4ea │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── ui-templates-invoice-c1137a92 │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── ui-templates-nda-markdown-a1c048ca │ │ │ ├── document.1.jpg │ │ │ ├── document.2.jpg │ │ │ ├── document.3.jpg │ │ │ ├── document.4.jpg │ │ │ ├── document.5.jpg │ │ │ └── document.pdf │ │ ├── ui-templates-receipt-644d535a │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ ├── ui-templates-report-charts-fe27a92e │ │ │ ├── document.1.jpg │ │ │ └── document.pdf │ │ └── ui-templates-scientific-report-7f68dcf5 │ │ │ ├── document.1.jpg │ │ │ ├── document.2.jpg │ │ │ └── document.pdf │ └── react-email-cover.avif ├── integrations │ └── onedoc.mdx ├── introduction.mdx ├── logo │ ├── dark.svg │ ├── light.svg │ ├── react-print-trim.png │ └── react-print.png ├── mint.json ├── quickstart.mdx ├── schema.json ├── snippets │ └── components.mdx ├── sortedDocs.json ├── troubleshooting │ └── faq.mdx └── ui │ ├── templates.mdx │ └── templates │ ├── invoice-advanced.mdx │ ├── invoice.mdx │ ├── nda-markdown.mdx │ ├── receipt.mdx │ ├── report-charts.mdx │ └── scientific-report.mdx ├── package-lock.json ├── package.json ├── patches └── @mhsdesign+jit-browser-tailwindcss+0.3.0.patch ├── src ├── client.ts ├── compile │ └── compile.tsx ├── css │ └── css.tsx ├── extensions │ ├── signature.ts │ └── signatureconstants.ts ├── footnote │ ├── footnote.css │ └── footnote.tsx ├── generic.css ├── index.ts ├── latex │ └── latex.tsx ├── markdown │ └── markdown.tsx ├── mdx.ts ├── server.ts ├── shell │ ├── shell.css │ └── shell.tsx ├── signature │ └── signature.tsx ├── tailwind │ ├── tailwind.tsx │ └── utils.resend.ts ├── ui │ └── templates │ │ ├── invoice-advanced.mdx │ │ ├── invoice.mdx │ │ ├── nda-markdown.mdx │ │ ├── receipt.mdx │ │ ├── report-charts.mdx │ │ └── scientific-report.mdx └── variables │ ├── headings.css │ ├── variables.css │ └── variables.tsx ├── tailwind.config.ts ├── tests └── compile.test.tsx ├── tsconfig.json └── tsup.config.ts /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Build and Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths-ignore: 8 | - "docs/**" 9 | - "docgen/**" 10 | - ".gitignore" 11 | 12 | jobs: 13 | build-and-publish: 14 | runs-on: ubuntu-latest 15 | permissions: 16 | contents: write 17 | steps: 18 | - uses: actions/create-github-app-token@v1 19 | id: app-token 20 | with: 21 | app-id: ${{ secrets.APP_ID }} 22 | private-key: ${{ secrets.APP_PRIVATE_KEY }} 23 | 24 | - uses: actions/checkout@v4 25 | with: 26 | token: ${{ steps.app-token.outputs.token }} 27 | 28 | - uses: actions/setup-node@v4 29 | with: 30 | node-version: 18 31 | cache: npm 32 | registry-url: "https://registry.npmjs.org" 33 | cache-dependency-path: ./package-lock.json 34 | - run: npm install 35 | working-directory: . 36 | - run: npm run build 37 | working-directory: . 38 | - run: npm test 39 | working-directory: . 40 | - run: npm version patch -m "Bump version to %s [skip ci]" --git-tag-version false 41 | working-directory: . 42 | - run: npm publish --access public 43 | working-directory: . 44 | env: 45 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 46 | - uses: stefanzweifel/git-auto-commit-action@v5 47 | with: 48 | commit_options: "--no-verify" 49 | commit_message: "Bump version [skip ci]" 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | test 3 | dist 4 | .DS_Store 5 | .tmp 6 | 7 | .env.local 8 | 9 | **/previews/**/index.html 10 | 11 | pack 12 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .github 2 | node_modules 3 | tsconfig.json 4 | docs 5 | src/ui 6 | docgen 7 | tests 8 | build 9 | tailwind.config.ts 10 | tsup.config.ts 11 | dist/mdx.* 12 | -------------------------------------------------------------------------------- /build/raw.ts: -------------------------------------------------------------------------------- 1 | import { Plugin } from "esbuild"; 2 | import { readFileSync } from "fs"; 3 | import path from "path"; 4 | 5 | export const RawPlugin: () => Plugin = () => { 6 | return { 7 | name: "inline-style", 8 | setup({ onResolve, onLoad }) { 9 | onResolve({ filter: /\?raw$/ }, (args) => { 10 | return { 11 | path: args.path, 12 | pluginData: { 13 | isAbsolute: path.isAbsolute(args.path), 14 | resolveDir: args.resolveDir, 15 | }, 16 | namespace: "raw-loader", 17 | }; 18 | }); 19 | 20 | onLoad({ filter: /.*/, namespace: "raw-loader" }, async (args) => { 21 | const resolvedPath = path.resolve( 22 | args.pluginData.resolveDir, 23 | args.path.replace(/\?raw$/, "") 24 | ); 25 | 26 | console.log("Resolving"); 27 | 28 | let contents = ""; 29 | 30 | try { 31 | contents = readFileSync(resolvedPath, "utf-8"); 32 | } catch (e) { 33 | console.error(e); 34 | } 35 | 36 | return { 37 | contents, 38 | loader: "text", 39 | }; 40 | }); 41 | }, 42 | }; 43 | }; 44 | -------------------------------------------------------------------------------- /docgen/base.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 2 | 3 | html, 4 | body { 5 | font-size: 28px; 6 | font-family: "Inter", sans-serif; 7 | } 8 | 9 | @page { 10 | size: A4; 11 | } 12 | -------------------------------------------------------------------------------- /docgen/buildExample.tsx: -------------------------------------------------------------------------------- 1 | import { EnrichedExample } from "./types"; 2 | import { formatSnippet } from "./utils"; 3 | import { renderPreview, baseCss } from "./renderPreview"; 4 | import type { CompileOptions } from "../src/compile/compile"; 5 | 6 | export const buildExample = async ( 7 | example: EnrichedExample, 8 | component: string, 9 | outputPath: string, 10 | compileOptions?: CompileOptions 11 | ) => { 12 | let markdown = ``; 13 | 14 | const snippet = await formatSnippet(example.templateString); 15 | 16 | const paths = await renderPreview( 17 | example.template, 18 | component, 19 | outputPath, 20 | true, 21 | compileOptions 22 | ); 23 | 24 | if (example.description) { 25 | markdown += `${example.description}\n\n`; 26 | } 27 | 28 | markdown += `\n\n`; 29 | 30 | // Check if the folder docs/previews contain the image 31 | 32 | markdown += `
33 | 34 | \`\`\`jsx 35 | import { ${component}${ 36 | example.imports ? `, ${example.imports.join(", ")}` : "" 37 | } } from "@fileforge/react-print";${ 38 | example.externalImports ? `\n${example.externalImports.join("\n")}` : "" 39 | } 40 | 41 | ${snippet} 42 | \`\`\` 43 | 44 | 45 | \`\`\`css 46 | ${baseCss} 47 | \`\`\` 48 | 49 |
\n\n`; 50 | 51 | // markdown += `Download the PDF example ↓\n\n`; 52 | 53 | return { 54 | markdown, 55 | }; 56 | }; 57 | -------------------------------------------------------------------------------- /docgen/buildFileMarkdown.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ConfigComponentDoc, 3 | EnrichedExample, 4 | ExtendedDocConfig, 5 | } from "./types"; 6 | import { ComponentDoc } from "react-docgen-typescript"; 7 | import { buildExample } from "./buildExample"; 8 | import { formatCamelCaseToTitle, safePropType } from "./utils"; 9 | import { doc } from "prettier"; 10 | 11 | export const buildFileMarkdown = async ( 12 | docConfig: ExtendedDocConfig, 13 | componentDocs: ComponentDoc[], 14 | outputPath: string 15 | ) => { 16 | let markdown = `--- 17 | title: ${docConfig.name} 18 | ${docConfig.icon ? `icon: ${docConfig.icon}` : ""} 19 | ${docConfig.description ? `description: "${docConfig.description}"` : ""} 20 | ---\n\n`; 21 | 22 | const componentKeys = new Set([ 23 | ...componentDocs.map((component) => component.displayName), 24 | ...Object.keys(docConfig.components), 25 | ]); 26 | 27 | for (const componentName of componentKeys) { 28 | let component = false as ComponentDoc | false; 29 | 30 | componentDocs.forEach((exportedComponent) => { 31 | if (exportedComponent.displayName === componentName) { 32 | component = exportedComponent as ComponentDoc; 33 | } 34 | }); 35 | 36 | let componentInfo: ConfigComponentDoc | false = false; 37 | 38 | let examples: { 39 | [key: string]: EnrichedExample; 40 | } = {}; 41 | 42 | try { 43 | examples = docConfig.components[componentName].examples || {}; 44 | componentInfo = docConfig.components[componentName] || false; 45 | } catch (e) {} 46 | 47 | let { client, server } = componentInfo || { client: true, server: true }; 48 | 49 | // markdown += `## ${componentName}\n\n`; 50 | if (component && component.description) { 51 | markdown += `${component.description}\n\n`; 52 | } 53 | 54 | markdown += `Support\n\n`; 55 | 56 | const check = 57 | ''; 58 | const noCheck = 59 | ''; 60 | 61 | markdown += `
${ 66 | client ? check : noCheck 67 | }Client-side
${ 68 | server ? check : noCheck 69 | }Server-side
\n\n`; 70 | 71 | 72 | if (Object.keys(examples).length > 0) { 73 | 74 | if (examples.default) { 75 | markdown += `#### Preview\n\n`; 76 | 77 | const { markdown: exampleMarkdown } = await buildExample( 78 | examples.default, 79 | componentName, 80 | outputPath, 81 | examples.default.compileOptions 82 | ); 83 | 84 | markdown += exampleMarkdown; 85 | } 86 | 87 | markdown += `### Examples\n\n`; 88 | 89 | if (Object.keys(examples).filter((key) => key !== "default").length > 0) { 90 | for (const [exampleName, example] of Object.entries(examples)) { 91 | if (exampleName === "default") { 92 | continue; 93 | } 94 | 95 | markdown += `#### ${ 96 | example.name || formatCamelCaseToTitle(exampleName) 97 | }\n\n`; 98 | 99 | const { markdown: exampleMarkdown } = await buildExample( 100 | example, 101 | componentName, 102 | outputPath, 103 | example.compileOptions 104 | ); 105 | 106 | markdown += exampleMarkdown; 107 | } 108 | } 109 | } else { 110 | markdown += `\`\`\`jsx\nimport { ${componentName} } from "@fileforge/react-print";\n\`\`\`\n\n`; 111 | } 112 | 113 | // if ( 114 | // component && 115 | // component.props && 116 | // Object.keys(component.props).length > 0 117 | // ) { 118 | // markdown += `### API\n\n\n\n`; 119 | 120 | // Object.entries(component.props).forEach(([propName, prop]) => { 121 | // markdown += `\n\n${ 124 | // prop.description 125 | // }\n\n${prop.defaultValue ? `Default: \`${JSON.stringify(prop.defaultValue.value)}\`\n\n` : ""}\n`; 126 | // }); 127 | 128 | // markdown += `\n`; 129 | // } 130 | } 131 | 132 | return markdown; 133 | }; 134 | -------------------------------------------------------------------------------- /docgen/buildTemplates.tsx: -------------------------------------------------------------------------------- 1 | import { glob } from "glob"; 2 | import { join, relative, dirname, basename, resolve } from "path"; 3 | import { build } from "tsup"; 4 | import { renderPreview } from "./renderPreview"; 5 | import React from "react"; 6 | import remarkFrontmatter from "remark-frontmatter"; 7 | import frontmatter from "front-matter"; 8 | import { promises as fs } from "fs"; 9 | import { formatCamelCaseToTitle, formatSnippet } from "./utils"; 10 | import { RawPlugin } from "../build/raw"; 11 | 12 | const tmpDir = join(__dirname, "../.tmp"); 13 | 14 | export async function buildTemplates() { 15 | const { default: mdx } = await import("@mdx-js/esbuild"); 16 | 17 | const templates = await glob(join(__dirname, "../src/ui/**/*.mdx")); 18 | 19 | return await Promise.all( 20 | templates.map(async (template) => { 21 | console.log("Building for template ", template); 22 | const outPath = 23 | join( 24 | tmpDir, 25 | dirname(relative(join(__dirname, "../src"), template)), 26 | basename(template, ".mdx") 27 | ) + ".js"; 28 | 29 | const docLocation = join( 30 | __dirname, 31 | `../docs/${dirname( 32 | relative(join(__dirname, "../src"), template) 33 | )}/${basename(template)}` 34 | ); 35 | 36 | await build({ 37 | entry: [template], 38 | esbuildPlugins: [ 39 | mdx({ 40 | remarkPlugins: [remarkFrontmatter], 41 | providerImportSource: "@fileforge/react-print/mdx", 42 | }), 43 | RawPlugin(), 44 | ], 45 | dts: false, 46 | outDir: dirname(outPath), 47 | format: "cjs", 48 | sourcemap: false, 49 | splitting: false, 50 | bundle: true, 51 | config: false, 52 | clean: true, 53 | }); 54 | 55 | const { default: Component } = await import(outPath); 56 | 57 | const RealComponent = Component.default ? Component.default : Component; 58 | 59 | const { attributes, body } = frontmatter<{ 60 | title?: string; 61 | description?: string; 62 | icon?: string; 63 | category?: string; 64 | }>( 65 | await fs 66 | .readFile(template, { 67 | encoding: "utf-8", 68 | }) 69 | .then((file) => file.toString()) 70 | ); 71 | 72 | const paths = await renderPreview( 73 | , 74 | `${dirname(relative(join(__dirname, "../src"), template)).replace( 75 | /\//g, 76 | " " 77 | )} ${basename(outPath, ".js")}`, 78 | docLocation, 79 | false 80 | ); 81 | 82 | const name = 83 | attributes.title || formatCamelCaseToTitle(basename(template, ".mdx")); 84 | 85 | let markdown = `--- 86 | title: ${name} 87 | ${attributes.icon ? `icon: ${attributes.icon}` : ""} 88 | category: ${attributes.category || "Uncategorized"} 89 | ---\n\n`; 90 | 91 | markdown += `\n\n`; 92 | 93 | markdown += `\`\`\`jsx 94 | ${await formatSnippet(body)} 95 | \`\`\`\n\n`; 96 | 97 | return { 98 | name, 99 | icon: attributes.icon, 100 | category: attributes.category, 101 | path: relative(join(__dirname, "../src"), template) 102 | .toLowerCase() 103 | .replace(/\.mdx$/, ""), 104 | image: resolve(docLocation, paths.imagePath), 105 | outputPath: docLocation, 106 | markdown, 107 | }; 108 | }) 109 | ); 110 | } 111 | 112 | export const buildTemplateList = async ( 113 | templates: Awaited>, 114 | path: string 115 | ) => { 116 | let markdown = `--- 117 | title: Browse 118 | icon: list 119 | ---\n\n`; 120 | 121 | // Group templates by category 122 | const categories: { 123 | [key: string]: Awaited>[0][]; 124 | } = templates.reduce((acc, template) => { 125 | const category = template.category || "Uncategorized"; 126 | if (!acc[category]) { 127 | acc[category] = []; 128 | } 129 | acc[category].push(template); 130 | return acc; 131 | }, {}); 132 | 133 | // Generate markdown for each category 134 | Object.entries(categories).forEach(([category, templates]) => { 135 | markdown += `## ${category}\n\n\n`; 136 | 137 | templates.forEach((template) => { 138 | markdown += ` 142 |
143 | 144 |
145 |
\n`; 146 | }); 147 | 148 | markdown += `
\n\n`; 149 | }); 150 | 151 | return markdown; 152 | }; 153 | -------------------------------------------------------------------------------- /docgen/pageBuilder/buildIntroduction.tsx: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | 4 | 5 | export const replaceInFile = (filePath: string, search: RegExp, replace: string) => { 6 | 7 | let fileContents = fs.readFileSync(filePath, 'utf8'); 8 | 9 | if (search.test(fileContents)) { 10 | // Replace the pattern with the new content 11 | fileContents = fileContents.replace(search, replace); 12 | 13 | // Write the updated content back to the file 14 | fs.writeFileSync(filePath, fileContents); 15 | console.log('Replacement successful'); 16 | } else { 17 | console.log('Pattern not found'); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /docgen/prune.ts: -------------------------------------------------------------------------------- 1 | // List all the folder paths contained in the docs/images/previews directory 2 | import { readdirSync, readFileSync, rmSync } from "fs"; 3 | import { glob } from "glob"; 4 | 5 | const dir = "docs/images/previews"; 6 | const folders = readdirSync(dir, { withFileTypes: true }) 7 | .filter((dirent) => dirent.isDirectory()) 8 | .map((dirent) => dirent.name); 9 | 10 | // List all the mdx files contained in the docs directory 11 | 12 | const mdxFiles = glob.sync("docs/**/*.mdx"); 13 | 14 | let unusedPreviews = folders; 15 | 16 | // For each mdx file, check if it contains a preview image 17 | mdxFiles.forEach((file) => { 18 | const content = readFileSync(file, "utf-8"); 19 | 20 | unusedPreviews = unusedPreviews.filter( 21 | (preview) => !content.includes(preview) 22 | ); 23 | }); 24 | 25 | // Remove the previews that are still in the unusued 26 | unusedPreviews.forEach((preview) => { 27 | const path = `${dir}/${preview}`; 28 | rmSync(path, { recursive: true }); 29 | }); 30 | -------------------------------------------------------------------------------- /docgen/renderPreview.tsx: -------------------------------------------------------------------------------- 1 | import { config } from "dotenv"; 2 | 3 | import { FileforgeClient } from "@fileforge/client"; 4 | import * as crypto from "crypto"; 5 | import * as path from "path"; 6 | import * as fs from "fs"; 7 | import { fromBuffer } from "pdf2pic"; 8 | import { glob } from "glob"; 9 | import { compile, CompileOptions } from "../dist"; 10 | import React from "react"; 11 | import { pipeline } from "stream/promises"; 12 | 13 | config({ path: ".env.local" }); 14 | config(); 15 | 16 | const ff = new FileforgeClient({ 17 | apiKey: process.env.ONEDOC_API_KEY!, 18 | }); 19 | 20 | export const baseCss = fs.readFileSync(path.join(__dirname, "./base.css")); 21 | export const indexCss = fs.readFileSync( 22 | path.join(__dirname, "../dist/index.css") 23 | ); 24 | 25 | export async function renderPreview( 26 | component: React.ReactElement, 27 | componentName: string, 28 | outputPath: string, 29 | useBaseCss: boolean = true, 30 | compileOptions?: CompileOptions 31 | ) { 32 | const Component = component; 33 | const Element = <>{Component}; 34 | 35 | const html = ` 36 | 37 | 38 | ${await compile(Element, compileOptions)}` as string; 39 | 40 | const hash = crypto.createHash("sha256"); 41 | hash.update(html); 42 | 43 | let id = hash.digest("hex"); 44 | id = componentName.replace(/ /g, "-").toLowerCase() + "-" + id.slice(0, 8); 45 | 46 | const targetFolder = path.join(__dirname, `../docs/images/previews/${id}/`); 47 | 48 | // If the file doesn't exist, create it by generating the document with Onedoc 49 | if (!fs.existsSync(targetFolder)) { 50 | const file = await ff.pdf.generate( 51 | [ 52 | new File([html], "index.html", { type: "text/html" }), 53 | useBaseCss 54 | ? new File([baseCss], "base.css", { type: "text/css" }) 55 | : new File([`@page { size: A4; }`], "base.css", { type: "text/css" }), 56 | new File([indexCss], "index.css", { type: "text/css" }), 57 | ], 58 | { 59 | options: { 60 | host: false, 61 | test: false, 62 | }, 63 | } 64 | ); 65 | 66 | // Create the directory 67 | fs.mkdirSync(targetFolder, { recursive: true }); 68 | 69 | // Write the HTML to a file 70 | fs.writeFileSync(path.join(targetFolder, "index.html"), html); 71 | 72 | await pipeline( 73 | file, 74 | fs.createWriteStream(path.join(targetFolder, "document.pdf")) 75 | ); 76 | 77 | const buffer = fs.readFileSync(path.join(targetFolder, "document.pdf")); 78 | 79 | const pdf2pic = fromBuffer(buffer, { 80 | density: 300, 81 | saveFilename: "document", 82 | savePath: targetFolder, 83 | format: "jpg", 84 | preserveAspectRatio: true, 85 | width: 1920, 86 | }); 87 | 88 | let currentPage = 1; 89 | 90 | while (true) { 91 | try { 92 | await pdf2pic(currentPage); 93 | } catch (e) { 94 | break; 95 | } 96 | 97 | currentPage++; 98 | } 99 | } 100 | 101 | const pages = (await glob(path.join(targetFolder, "*.jpg"))).sort(); 102 | const pdf = await glob(path.join(targetFolder, "*.pdf")); 103 | const imagePath = path.relative(path.dirname(outputPath), pages[0]); 104 | const pdfPath = path.relative(path.dirname(outputPath), pdf[0]); 105 | 106 | return { 107 | imagePath, 108 | pdfPath, 109 | }; 110 | } 111 | -------------------------------------------------------------------------------- /docgen/types.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import type { CompileOptions } from "../src/compile/compile"; 3 | 4 | export interface Example { 5 | description?: string; 6 | name?: string; 7 | template: React.ReactElement; 8 | compileOptions?: CompileOptions; 9 | imports?: string[]; 10 | externalImports?: string[]; 11 | } 12 | 13 | export interface EnrichedExample extends Example { 14 | templateString: string; 15 | } 16 | 17 | export interface ConfigComponentDoc { 18 | server: boolean; 19 | client: boolean; 20 | examples?: { 21 | [key: string]: T; 22 | }; 23 | } 24 | 25 | export interface DocConfig { 26 | name?: string; 27 | icon?: string; 28 | description: string; 29 | components: { 30 | [componentName: string]: ConfigComponentDoc; 31 | }; 32 | } 33 | 34 | export type ExtendedDocConfig = DocConfig; 35 | -------------------------------------------------------------------------------- /docgen/utils.ts: -------------------------------------------------------------------------------- 1 | import * as ts from "typescript"; 2 | import { DocConfig, ExtendedDocConfig } from "./types"; 3 | import * as prettier from "prettier"; 4 | 5 | export const formatCamelCaseToTitle = (str: string) => { 6 | // Convert camelCase to Title Case with spaces 7 | return str 8 | .replace(/([A-Z])/g, " $1") 9 | .replace(/^./, (str) => str.toUpperCase()); 10 | }; 11 | 12 | const listProperties = (node: ts.ObjectLiteralExpression) => { 13 | const properties = {}; 14 | 15 | node.properties.forEach((property) => { 16 | if (ts.isPropertyAssignment(property)) { 17 | properties[property.name.getText()] = property.initializer; 18 | } 19 | }); 20 | 21 | return properties; 22 | }; 23 | 24 | const extractTemplates = (node) => { 25 | const templates = {}; 26 | 27 | const components = listProperties( 28 | listProperties(node)["components"] as ts.ObjectLiteralExpression 29 | ); 30 | 31 | Object.entries(components).forEach(([componentName, value]) => { 32 | templates[componentName] = {}; 33 | 34 | let examples = {}; 35 | 36 | try { 37 | examples = listProperties( 38 | listProperties(value as ts.ObjectLiteralExpression)[ 39 | "examples" 40 | ] as ts.ObjectLiteralExpression 41 | ); 42 | } catch (e) {} 43 | 44 | Object.entries(examples).forEach(([exampleName, value]) => { 45 | const template = listProperties(value as ts.ObjectLiteralExpression)[ 46 | "template" 47 | ]; 48 | 49 | templates[componentName][exampleName] = template.getText(); 50 | }); 51 | }); 52 | 53 | return templates; 54 | }; 55 | 56 | export const getTemplateContents = (filePath: string) => { 57 | // Load the file contents to the typescript ast 58 | const sourceFile = ts.createSourceFile( 59 | filePath, 60 | ts.sys.readFile(filePath) || "", 61 | ts.ScriptTarget.Latest, 62 | true 63 | ); 64 | 65 | let templates = {}; 66 | 67 | sourceFile.forEachChild((node) => { 68 | if (ts.isVariableStatement(node)) { 69 | node.declarationList.declarations.forEach((declaration) => { 70 | if (declaration.name.getText() === "__docConfig") { 71 | templates = extractTemplates(declaration.initializer); 72 | } 73 | }); 74 | } 75 | }); 76 | 77 | return templates; 78 | }; 79 | 80 | export const mergeTemplateInfo = ( 81 | docInfo: DocConfig, 82 | templates: any 83 | ): ExtendedDocConfig => { 84 | Object.entries(docInfo.components).forEach(([componentName, value]) => { 85 | Object.entries(value.examples || {}).forEach(([exampleName, example]) => { 86 | // @ts-ignore 87 | example.templateString = templates[componentName][exampleName]; 88 | }); 89 | }); 90 | 91 | return docInfo as ExtendedDocConfig; 92 | }; 93 | 94 | export const formatSnippet = (snippet: string) => { 95 | return prettier.format(snippet, { 96 | parser: "typescript", 97 | }); 98 | }; 99 | 100 | export const safePropType = (str: string) => { 101 | // Replace all " by ' to avoid conflicts with markdown 102 | return str.replace(/"/g, "'"); 103 | }; 104 | -------------------------------------------------------------------------------- /docs/api-reference/endpoint/create.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Create Plant' 3 | openapi: 'POST /plants' 4 | --- 5 | -------------------------------------------------------------------------------- /docs/api-reference/endpoint/delete.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Delete Plant' 3 | openapi: 'DELETE /plants/{id}' 4 | --- 5 | -------------------------------------------------------------------------------- /docs/api-reference/endpoint/get.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Get Plants' 3 | openapi: 'GET /plants' 4 | --- 5 | -------------------------------------------------------------------------------- /docs/api-reference/introduction.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Introduction' 3 | description: 'Example section for showcasing API endpoints' 4 | --- 5 | 6 | 7 | If you're not looking to build API reference documentation, you can delete 8 | this section by removing the api-reference folder. 9 | 10 | 11 | ## Welcome 12 | 13 | There are two ways to build API documentation: [OpenAPI](https://mintlify.com/docs/api-playground/openapi/setup) and [MDX components](https://mintlify.com/docs/api-playground/mdx/configuration). For the starter kit, we are using the following OpenAPI specification. 14 | 15 | 20 | View the OpenAPI specification file 21 | 22 | 23 | ## Authentication 24 | 25 | All API endpoints are authenticated using Bearer tokens and picked up from the specification file. 26 | 27 | ```json 28 | "security": [ 29 | { 30 | "bearerAuth": [] 31 | } 32 | ] 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/api-reference/openapi.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi": "3.0.1", 3 | "info": { 4 | "title": "OpenAPI Plant Store", 5 | "description": "A sample API that uses a plant store as an example to demonstrate features in the OpenAPI specification", 6 | "license": { 7 | "name": "MIT" 8 | }, 9 | "version": "1.0.0" 10 | }, 11 | "servers": [ 12 | { 13 | "url": "http://sandbox.mintlify.com" 14 | } 15 | ], 16 | "security": [ 17 | { 18 | "bearerAuth": [] 19 | } 20 | ], 21 | "paths": { 22 | "/plants": { 23 | "get": { 24 | "description": "Returns all plants from the system that the user has access to", 25 | "parameters": [ 26 | { 27 | "name": "limit", 28 | "in": "query", 29 | "description": "The maximum number of results to return", 30 | "schema": { 31 | "type": "integer", 32 | "format": "int32" 33 | } 34 | } 35 | ], 36 | "responses": { 37 | "200": { 38 | "description": "Plant response", 39 | "content": { 40 | "application/json": { 41 | "schema": { 42 | "type": "array", 43 | "items": { 44 | "$ref": "#/components/schemas/Plant" 45 | } 46 | } 47 | } 48 | } 49 | }, 50 | "400": { 51 | "description": "Unexpected error", 52 | "content": { 53 | "application/json": { 54 | "schema": { 55 | "$ref": "#/components/schemas/Error" 56 | } 57 | } 58 | } 59 | } 60 | } 61 | }, 62 | "post": { 63 | "description": "Creates a new plant in the store", 64 | "requestBody": { 65 | "description": "Plant to add to the store", 66 | "content": { 67 | "application/json": { 68 | "schema": { 69 | "$ref": "#/components/schemas/NewPlant" 70 | } 71 | } 72 | }, 73 | "required": true 74 | }, 75 | "responses": { 76 | "200": { 77 | "description": "plant response", 78 | "content": { 79 | "application/json": { 80 | "schema": { 81 | "$ref": "#/components/schemas/Plant" 82 | } 83 | } 84 | } 85 | }, 86 | "400": { 87 | "description": "unexpected error", 88 | "content": { 89 | "application/json": { 90 | "schema": { 91 | "$ref": "#/components/schemas/Error" 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | }, 99 | "/plants/{id}": { 100 | "delete": { 101 | "description": "Deletes a single plant based on the ID supplied", 102 | "parameters": [ 103 | { 104 | "name": "id", 105 | "in": "path", 106 | "description": "ID of plant to delete", 107 | "required": true, 108 | "schema": { 109 | "type": "integer", 110 | "format": "int64" 111 | } 112 | } 113 | ], 114 | "responses": { 115 | "204": { 116 | "description": "Plant deleted", 117 | "content": {} 118 | }, 119 | "400": { 120 | "description": "unexpected error", 121 | "content": { 122 | "application/json": { 123 | "schema": { 124 | "$ref": "#/components/schemas/Error" 125 | } 126 | } 127 | } 128 | } 129 | } 130 | } 131 | } 132 | }, 133 | "components": { 134 | "schemas": { 135 | "Plant": { 136 | "required": [ 137 | "name" 138 | ], 139 | "type": "object", 140 | "properties": { 141 | "name": { 142 | "description": "The name of the plant", 143 | "type": "string" 144 | }, 145 | "tag": { 146 | "description": "Tag to specify the type", 147 | "type": "string" 148 | } 149 | } 150 | }, 151 | "NewPlant": { 152 | "allOf": [ 153 | { 154 | "$ref": "#/components/schemas/Plant" 155 | }, 156 | { 157 | "required": [ 158 | "id" 159 | ], 160 | "type": "object", 161 | "properties": { 162 | "id": { 163 | "description": "Identification number of the plant", 164 | "type": "integer", 165 | "format": "int64" 166 | } 167 | } 168 | } 169 | ] 170 | }, 171 | "Error": { 172 | "required": [ 173 | "error", 174 | "message" 175 | ], 176 | "type": "object", 177 | "properties": { 178 | "error": { 179 | "type": "integer", 180 | "format": "int32" 181 | }, 182 | "message": { 183 | "type": "string" 184 | } 185 | } 186 | } 187 | }, 188 | "securitySchemes": { 189 | "bearerAuth": { 190 | "type": "http", 191 | "scheme": "bearer" 192 | } 193 | } 194 | } 195 | } -------------------------------------------------------------------------------- /docs/components/compile/compile.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: compile 3 | 4 | 5 | --- 6 | 7 | Support 8 | 9 |
Client-side
Server-side
14 | 15 | #### Preview 16 | 17 | A simple function to compile a React component to an HTML string with the Onedoc print styles. 18 | ```jsx 19 | const html = await compile(); 20 | ``` 21 | 22 | 23 | 24 |
25 | 26 | ```jsx 27 | import { compile } from "@fileforge/react-print"; 28 | 29 | 30 |
Hello World!
31 |
; 32 | 33 | ``` 34 |
35 | 36 | ```css 37 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 38 | 39 | html, 40 | body { 41 | font-size: 28px; 42 | font-family: "Inter", sans-serif; 43 | } 44 | 45 | @page { 46 | size: A4; 47 | } 48 | 49 | ``` 50 | 51 |
52 | 53 | ### Examples 54 | 55 | #### Emotion CSS 56 | 57 | Pass `{ emotion: true }` as the second compile option to merge and extract critical CSS using Emotion. Some libraries such as Chakra UI require this option to work correctly. 58 | 59 | ```jsx 60 | const html = await compile(, { emotion: true }); 61 | ``` 62 | 63 | 64 | 65 |
66 | 67 | ```jsx 68 | import { compile } from "@fileforge/react-print"; 69 | import { Button, ChakraProvider, extendTheme } from "@chakra-ui/react"; 70 | 71 | <> 72 | 73 | 74 | 75 | ; 76 | 77 | ``` 78 | 79 | 80 | ```css 81 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 82 | 83 | html, 84 | body { 85 | font-size: 28px; 86 | font-family: "Inter", sans-serif; 87 | } 88 | 89 | @page { 90 | size: A4; 91 | } 92 | 93 | ``` 94 | 95 |
96 | 97 | -------------------------------------------------------------------------------- /docs/components/css/css.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: CSS 3 | 4 | 5 | --- 6 | 7 | Support 8 | 9 |
Client-side
Server-side
14 | 15 | #### Preview 16 | 17 | Use a simple CSS tag to support CSS in your document. 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { CSS } from "@fileforge/react-print"; 25 | 26 | {`@page { size: a4 landscape; }`}; 27 | 28 | ``` 29 | 30 | 31 | ```css 32 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 33 | 34 | html, 35 | body { 36 | font-size: 28px; 37 | font-family: "Inter", sans-serif; 38 | } 39 | 40 | @page { 41 | size: A4; 42 | } 43 | 44 | ``` 45 | 46 |
47 | 48 | ### Examples 49 | 50 | -------------------------------------------------------------------------------- /docs/components/css/font.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Font 3 | 4 | 5 | --- 6 | 7 | Support 8 | 9 |
Client-side
Server-side
14 | 15 | #### Preview 16 | 17 | Load a Google Font its URL. This will allow you to use the font in your document. 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { Font } from "@fileforge/react-print"; 25 | 26 | 27 | 28 |

29 | This text uses the Roboto Light font. 30 |

31 |
; 32 | 33 | ``` 34 |
35 | 36 | ```css 37 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 38 | 39 | html, 40 | body { 41 | font-size: 28px; 42 | font-family: "Inter", sans-serif; 43 | } 44 | 45 | @page { 46 | size: A4; 47 | } 48 | 49 | ``` 50 | 51 |
52 | 53 | ### Examples 54 | 55 | -------------------------------------------------------------------------------- /docs/components/css/margins.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Margins 3 | 4 | 5 | --- 6 | 7 | Support 8 | 9 |
Client-side
Server-side
14 | 15 | #### Preview 16 | 17 | Set the page ratio and margin sizes in px. You can also use the `@page` at-rule in CSS to manage all aspects of printed pages. More on this [here](https://developer.mozilla.org/en-US/docs/Web/CSS/@page). 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { Margins } from "@fileforge/react-print"; 25 | 26 | 27 | {`body{background-color:lightblue}`} 28 | 29 |
Hello world!
30 |
; 31 | 32 | ``` 33 |
34 | 35 | ```css 36 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 37 | 38 | html, 39 | body { 40 | font-size: 28px; 41 | font-family: "Inter", sans-serif; 42 | } 43 | 44 | @page { 45 | size: A4; 46 | } 47 | 48 | ``` 49 | 50 |
51 | 52 | ### Examples 53 | 54 | -------------------------------------------------------------------------------- /docs/components/footnote/footnote.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Footnote 3 | 4 | 5 | --- 6 | 7 | Creates an automatically numbered footnote. This will remove the footnote content from the document flow and place it at the bottom of the page. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | #### Preview 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { Footnote } from "@fileforge/react-print"; 25 | 26 |
27 | This is a footnote to explaning what CSS{" "} 28 | 29 | CSS is the acronym of “Cascading Style Sheets”. CSS is a computer language 30 | for laying out and structuring web pages (HTML or XML). 31 | {" "} 32 | is. 33 |
; 34 | 35 | ``` 36 |
37 | 38 | ```css 39 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 40 | 41 | html, 42 | body { 43 | font-size: 28px; 44 | font-family: "Inter", sans-serif; 45 | } 46 | 47 | @page { 48 | size: A4; 49 | } 50 | 51 | ``` 52 | 53 |
54 | 55 | ### Examples 56 | 57 | -------------------------------------------------------------------------------- /docs/components/latex/latex.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Latex 3 | 4 | 5 | --- 6 | 7 | Support 8 | 9 |
Client-side
Server-side
14 | 15 | #### Preview 16 | 17 | Use a simple Latex tag to support Latex in your document. 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { Latex } from "@fileforge/react-print"; 25 | 26 | {String.raw`\frac{1}{2}`}; 27 | 28 | ``` 29 | 30 | 31 | ```css 32 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 33 | 34 | html, 35 | body { 36 | font-size: 28px; 37 | font-family: "Inter", sans-serif; 38 | } 39 | 40 | @page { 41 | size: A4; 42 | } 43 | 44 | ``` 45 | 46 |
47 | 48 | ### Examples 49 | 50 | #### Complex 51 | 52 | Write complex LaTeX formulas in your document. 53 | 54 | 55 | 56 |
57 | 58 | ```jsx 59 | import { Latex } from "@fileforge/react-print"; 60 | 61 | {String.raw`% \f is defined as #1f(#2) using the macro 62 | \f\relax{x} = \int_{-\infty}^\infty 63 | \f\hat\xi\,e^{2 \pi i \xi x} 64 | \,d\xi`}; 65 | 66 | ``` 67 | 68 | 69 | ```css 70 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 71 | 72 | html, 73 | body { 74 | font-size: 28px; 75 | font-family: "Inter", sans-serif; 76 | } 77 | 78 | @page { 79 | size: A4; 80 | } 81 | 82 | ``` 83 | 84 |
85 | 86 | -------------------------------------------------------------------------------- /docs/components/shell/currentpagetop.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: CurrentPageTop 3 | 4 | 5 | --- 6 | 7 | Displays content in the top of the current page. 8 | 9 | This component will override the content of the `PageTop` component for the current page. 10 | 11 | Support 12 | 13 |
Client-side
Server-side
18 | 19 | #### Preview 20 | 21 | 22 | 23 |
24 | 25 | ```jsx 26 | import { CurrentPageTop } from "@fileforge/react-print"; 27 | 28 | ; 29 | 30 | ``` 31 | 32 | 33 | ```css 34 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 35 | 36 | html, 37 | body { 38 | font-size: 28px; 39 | font-family: "Inter", sans-serif; 40 | } 41 | 42 | @page { 43 | size: A4; 44 | } 45 | 46 | ``` 47 | 48 |
49 | 50 | ### Examples 51 | 52 | -------------------------------------------------------------------------------- /docs/components/shell/floatbottom.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: FloatBottom 3 | 4 | 5 | --- 6 | 7 | Floats the content to the bottom of the page. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | #### Preview 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { FloatBottom } from "@fileforge/react-print"; 25 | 26 | Here are some floated contents; 27 | 28 | ``` 29 | 30 | 31 | ```css 32 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 33 | 34 | html, 35 | body { 36 | font-size: 28px; 37 | font-family: "Inter", sans-serif; 38 | } 39 | 40 | @page { 41 | size: A4; 42 | } 43 | 44 | ``` 45 | 46 |
47 | 48 | ### Examples 49 | 50 | -------------------------------------------------------------------------------- /docs/components/shell/nobreak.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: NoBreak 3 | 4 | 5 | --- 6 | 7 | Prevents a page break. Wrap this component around content that should not be broken across pages. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | #### Preview 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { NoBreak } from "@fileforge/react-print"; 25 | 26 | This content will not be split between two pages.; 27 | 28 | ``` 29 | 30 | 31 | ```css 32 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 33 | 34 | html, 35 | body { 36 | font-size: 28px; 37 | font-family: "Inter", sans-serif; 38 | } 39 | 40 | @page { 41 | size: A4; 42 | } 43 | 44 | ``` 45 | 46 |
47 | 48 | ### Examples 49 | 50 | -------------------------------------------------------------------------------- /docs/components/shell/pagebottom.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: PageBottom 3 | 4 | 5 | --- 6 | 7 | Displays content in the bottom of all the pages. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | #### Preview 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { PageBottom } from "@fileforge/react-print"; 25 | 26 | ; 27 | 28 | ``` 29 | 30 | 31 | ```css 32 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 33 | 34 | html, 35 | body { 36 | font-size: 28px; 37 | font-family: "Inter", sans-serif; 38 | } 39 | 40 | @page { 41 | size: A4; 42 | } 43 | 44 | ``` 45 | 46 |
47 | 48 | ### Examples 49 | 50 | -------------------------------------------------------------------------------- /docs/components/shell/pagebreak.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: PageBreak 3 | 4 | 5 | --- 6 | 7 | Forces a page break. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | #### Preview 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { PageBreak } from "@fileforge/react-print"; 25 | 26 |
27 |
Hello on this page
28 | 29 |
World on that page
30 |
; 31 | 32 | ``` 33 |
34 | 35 | ```css 36 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 37 | 38 | html, 39 | body { 40 | font-size: 28px; 41 | font-family: "Inter", sans-serif; 42 | } 43 | 44 | @page { 45 | size: A4; 46 | } 47 | 48 | ``` 49 | 50 |
51 | 52 | ### Examples 53 | 54 | -------------------------------------------------------------------------------- /docs/components/shell/pagetop.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: PageTop 3 | 4 | 5 | --- 6 | 7 | Displays content in the top of all the pages. 8 | 9 | This component should be placed as early as possible in the document and will apply to all subsequent pages. 10 | 11 | Support 12 | 13 |
Client-side
Server-side
18 | 19 | #### Preview 20 | 21 | 22 | 23 |
24 | 25 | ```jsx 26 | import { PageTop } from "@fileforge/react-print"; 27 | 28 | ; 29 | 30 | ``` 31 | 32 | 33 | ```css 34 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 35 | 36 | html, 37 | body { 38 | font-size: 28px; 39 | font-family: "Inter", sans-serif; 40 | } 41 | 42 | @page { 43 | size: A4; 44 | } 45 | 46 | ``` 47 | 48 |
49 | 50 | ### Examples 51 | 52 | -------------------------------------------------------------------------------- /docs/components/signature/field.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Field 3 | 4 | 5 | --- 6 | 7 | Support 8 | 9 |
Client-side
Server-side
14 | 15 | #### Preview 16 | 17 | The created fields can be signed as-is in Acrobat Reader or other PDF viewers, using Onedoc's signature API, or through other e-signature services like [DocuSign](https://developers.docusign.com/docs/esign-rest-api/esign101/concepts/tabs/pdf-transform/). 18 | 19 | Supported fields: 20 | 21 | | Field Type | Description | 22 | |------------|-------------| 23 | | signHere | Signature field | 24 | | signHereOptional | Optional signature field | 25 | | signInitialHere | Initials field | 26 | | signInitialHereOptional | Optional initials field | 27 | | company | Company name field | 28 | | dateSigned | Date signed field | 29 | | title | Title field | 30 | | fullName | Full name field | 31 | | lastName | Last name field | 32 | | firstName | First name field | 33 | | emailAddress | Email address field | 34 | | number | Number field | 35 | | date | Date field | 36 | | ssn | Social Security Number field | 37 | | zip5 | ZIP code field | 38 | | zip5dash4 | ZIP code with 4-digit extension field | 39 | | note | Note field | 40 | | list | List field | 41 | | checkbox | Checkbox field | 42 | | radio | Radio button field | 43 | | approve | Approve button field | 44 | | decline | Decline button field | 45 | | view | View button field | 46 | | signerAttachment | Signer attachment field | 47 | | signerAttachmentOptional | Optional signer attachment field | 48 | 49 | 50 | 51 |
52 | 53 | ```jsx 54 | import { Field } from "@fileforge/react-print"; 55 | 56 | <> 57 | 58 |

Signature

59 |
60 | By 61 |
62 | 68 |
69 | 75 |
76 | 81 |
82 |
83 | ; 84 | 85 | ``` 86 |
87 | 88 | ```css 89 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 90 | 91 | html, 92 | body { 93 | font-size: 28px; 94 | font-family: "Inter", sans-serif; 95 | } 96 | 97 | @page { 98 | size: A4; 99 | } 100 | 101 | ``` 102 | 103 |
104 | 105 | ### Examples 106 | 107 | -------------------------------------------------------------------------------- /docs/components/tailwind/tailwind.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tailwind 3 | 4 | 5 | --- 6 | 7 | Support 8 | 9 |
Client-side
Server-side
14 | 15 | #### Preview 16 | 17 | Use a simple Tailwind tag to support Tailwind in your document. 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { Tailwind } from "@fileforge/react-print"; 25 | 26 | 27 |
28 |

29 | This is a Tailwind component. All children of this component will have 30 | access to the Tailwind CSS classes. 31 |

32 |
; 33 | 34 | ``` 35 |
36 | 37 | ```css 38 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 39 | 40 | html, 41 | body { 42 | font-size: 28px; 43 | font-family: "Inter", sans-serif; 44 | } 45 | 46 | @page { 47 | size: A4; 48 | } 49 | 50 | ``` 51 | 52 |
53 | 54 | ### Examples 55 | 56 | #### Custom Tailwind config 57 | 58 | You can also pass a custom Tailwind config to the Tailwind component. 59 | 60 | 61 | 62 |
63 | 64 | ```jsx 65 | import { Tailwind } from "@fileforge/react-print"; 66 | 67 | 78 |
79 |

80 | This is a Tailwind component. All children of this component will have 81 | access to the Tailwind CSS classes. 82 |

83 |
; 84 | 85 | ``` 86 |
87 | 88 | ```css 89 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 90 | 91 | html, 92 | body { 93 | font-size: 28px; 94 | font-family: "Inter", sans-serif; 95 | } 96 | 97 | @page { 98 | size: A4; 99 | } 100 | 101 | ``` 102 | 103 |
104 | 105 | #### Disable Preflight 106 | 107 | You can disable the Tailwind Preflight CSS. 108 | 109 | 110 | 111 |
112 | 113 | ```jsx 114 | import { Tailwind } from "@fileforge/react-print"; 115 | 116 | 123 |
124 |

Level 1 Header

125 |

126 | This is a Tailwind component. All children of this component will have 127 | access to the Tailwind CSS classes. 128 |

129 |
; 130 | 131 | ``` 132 |
133 | 134 | ```css 135 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 136 | 137 | html, 138 | body { 139 | font-size: 28px; 140 | font-family: "Inter", sans-serif; 141 | } 142 | 143 | @page { 144 | size: A4; 145 | } 146 | 147 | ``` 148 | 149 |
150 | 151 | -------------------------------------------------------------------------------- /docs/components/variables/pagenumber.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: PageNumber 3 | 4 | 5 | --- 6 | 7 | Returns the current page number. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | #### Preview 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { PageNumber } from "@fileforge/react-print"; 25 | 26 | ; 27 | 28 | ``` 29 | 30 | 31 | ```css 32 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 33 | 34 | html, 35 | body { 36 | font-size: 28px; 37 | font-family: "Inter", sans-serif; 38 | } 39 | 40 | @page { 41 | size: A4; 42 | } 43 | 44 | ``` 45 | 46 |
47 | 48 | ### Examples 49 | 50 | #### Custom Style 51 | 52 | You can use a custom CSS counter-style, by passing a known name or a custom counter style. 53 | 54 | 55 | 56 |
57 | 58 | ```jsx 59 | import { PageNumber } from "@fileforge/react-print"; 60 | 61 | ; 62 | 63 | ``` 64 | 65 | 66 | ```css 67 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 68 | 69 | html, 70 | body { 71 | font-size: 28px; 72 | font-family: "Inter", sans-serif; 73 | } 74 | 75 | @page { 76 | size: A4; 77 | } 78 | 79 | ``` 80 | 81 |
82 | 83 | -------------------------------------------------------------------------------- /docs/components/variables/pagesnumber.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: PagesNumber 3 | 4 | 5 | --- 6 | 7 | Returns the total number of pages. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | #### Preview 18 | 19 | 20 | 21 |
22 | 23 | ```jsx 24 | import { PagesNumber, PageNumber } from "@fileforge/react-print"; 25 | 26 | <> 27 | 28 | {" of "} 29 | 30 | ; 31 | 32 | ``` 33 | 34 | 35 | ```css 36 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 37 | 38 | html, 39 | body { 40 | font-size: 28px; 41 | font-family: "Inter", sans-serif; 42 | } 43 | 44 | @page { 45 | size: A4; 46 | } 47 | 48 | ``` 49 | 50 |
51 | 52 | ### Examples 53 | 54 | -------------------------------------------------------------------------------- /docs/components/variables/runningh1.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: RunningH1 3 | 4 | 5 | --- 6 | 7 | Returns the current page's running header of level 1. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | #### Preview 18 | 19 | Show the current running header of level 1 in the page header. All running headers are reset when any of their parent headings are encountered (e.g. a level 2 heading resets the level 3, 4, 5 and 6 headings). 20 | 21 | 22 | 23 |
24 | 25 | ```jsx 26 | import { RunningH1 } from "@fileforge/react-print"; 27 | 28 | 29 | 30 | 31 | 32 |

Heading of level 1

33 |
; 34 | 35 | ``` 36 |
37 | 38 | ```css 39 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap"); 40 | 41 | html, 42 | body { 43 | font-size: 28px; 44 | font-family: "Inter", sans-serif; 45 | } 46 | 47 | @page { 48 | size: A4; 49 | } 50 | 51 | ``` 52 | 53 |
54 | 55 | ### Examples 56 | 57 | -------------------------------------------------------------------------------- /docs/components/variables/runningh2.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: RunningH2 3 | 4 | 5 | --- 6 | 7 | Returns the current page's running header of level 2. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | ```jsx 18 | import { RunningH2 } from "@fileforge/react-print"; 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /docs/components/variables/runningh3.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: RunningH3 3 | 4 | 5 | --- 6 | 7 | Returns the current page's running header of level 3. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | ```jsx 18 | import { RunningH3 } from "@fileforge/react-print"; 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /docs/components/variables/runningh4.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: RunningH4 3 | 4 | 5 | --- 6 | 7 | Returns the current page's running header of level 4. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | ```jsx 18 | import { RunningH4 } from "@fileforge/react-print"; 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /docs/components/variables/runningh5.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: RunningH5 3 | 4 | 5 | --- 6 | 7 | Returns the current page's running header of level 5. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | ```jsx 18 | import { RunningH5 } from "@fileforge/react-print"; 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /docs/components/variables/runningh6.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: RunningH6 3 | 4 | 5 | --- 6 | 7 | Returns the current page's running header of level 6. 8 | 9 | Support 10 | 11 |
Client-side
Server-side
16 | 17 | ```jsx 18 | import { RunningH6 } from "@fileforge/react-print"; 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /docs/contributing.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Contributing' 3 | sidebarTitle: 'Contributing' 4 | description: 'Wanna help? Awesome! There are many ways you can contribute.' 5 | icon: 'fa-solid fa-code-pull-request' 6 | --- 7 | 8 | ## Improving the docs 9 | 10 | Documentation is extremely important and takes a fair deal of time and effort to write and keep updated. Everything is written in [Markdown](https://www.markdownguide.org/) to facilitate the process of contributing. 11 | 12 | 17 | 18 | 19 | }> 20 | 21 | ## Docs Setup Guide 22 | 23 | 1. Clone the repository: 24 | 25 | ```sh 26 | git clone https://github.com/fileforge/react-print-pdf 27 | ``` 28 | 29 | 2. Install all dependencies: 30 | 31 | ```sh 32 | pnpm install 33 | ``` 34 | 35 | 3. Run local servers and watch for changes: 36 | 37 | ```sh 38 | pnpm dev 39 | ``` 40 | 41 | 4. Make your changes under the `/docs` folder and see a live preview at [localhost:3000](http://localhost:3000). 42 | 43 | 5. Submit a pull request. 44 | 45 | 46 | 47 | ## Building new components 48 | 49 | We're open to expanding the catalog of components to cover as many use cases as possible. We suggest to open an issue for discussion first to make sure your idea is aligned with the project goals. 50 | 51 | 56 | 57 | 58 | }> 59 | 60 | ## Components Setup Guide 61 | 62 | 1. Clone the repository: 63 | 64 | ```sh 65 | git clone https://github.com/fileforge/react-print-pdf 66 | ``` 67 | 68 | 2. Install pip2pic dependencies: 69 | 70 | ```sh 71 | brew update 72 | brew install gs graphicsmagick 73 | ``` 74 | 75 | 3. Install pip2pic: 76 | 77 | ```sh 78 | npm install pdf2pic 79 | ``` 80 | 81 | 4. Install all dependencies: 82 | 83 | ```sh 84 | pnpm install 85 | ``` 86 | 87 | 5. Run local servers and watch for changes: 88 | 89 | ```sh 90 | pnpm dev 91 | ``` 92 | 93 | 6. Add a new folder under `src` and build your component. 94 | 95 | 7. Don't forget to add tests. 96 | 97 | 8. Submit a pull request. 98 | 99 | 100 | 101 | ## Opening issues 102 | 103 | Open an issue to report bugs or to propose new features. 104 | 105 | - **Reporting bugs**: describe the bug as clearly as you can, including steps to reproduce, what happened and what you were expecting to happen. Also include browser version, OS and other related software's (npm, Node.js, etc) versions when applicable. 106 | 107 | - **Suggesting features**: explain the proposed feature, what it should do, why it is useful, how users should use it. Give us as much info as possible so it will be easier to discuss, access and implement the proposed feature. When you're unsure about a certain aspect of the feature, feel free to leave it open for others to discuss and find an appropriate solution. 108 | 109 | ## Proposing pull requests 110 | 111 | Pull requests are very welcome. Note that if you are going to propose drastic changes, be sure to open an issue for discussion first, to make sure that your PR will be accepted before you spend effort coding it. 112 | 113 | - **Forking the repository**: clone it locally and create a branch for your proposed bug fix or new feature. Avoid working directly on the main branch. 114 | 115 | - **Making changes**: implement your bug fix or feature, write tests to cover it and make sure all tests are passing. Then commit your changes, push your bug fix/feature branch to the origin (your forked repo) and open a pull request to the upstream (the repository you originally forked)'s main branch. -------------------------------------------------------------------------------- /docs/development.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Development' 3 | description: 'Learn how to preview changes locally' 4 | --- 5 | 6 | 7 | **Prerequisite** You should have installed Node.js (version 18.10.0 or 8 | higher). 9 | 10 | 11 | Step 1. Install Mintlify on your OS: 12 | 13 | 14 | 15 | ```bash npm 16 | npm i -g mintlify 17 | ``` 18 | 19 | ```bash yarn 20 | yarn global add mintlify 21 | ``` 22 | 23 | 24 | 25 | Step 2. Go to the docs are located (where you can find `mint.json`) and run the following command: 26 | 27 | ```bash 28 | mintlify dev 29 | ``` 30 | 31 | The documentation website is now available at `http://localhost:3000`. 32 | 33 | ### Custom Ports 34 | 35 | Mintlify uses port 3000 by default. You can use the `--port` flag to customize the port Mintlify runs on. For example, use this command to run in port 3333: 36 | 37 | ```bash 38 | mintlify dev --port 3333 39 | ``` 40 | 41 | You will see an error like this if you try to run Mintlify in a port that's already taken: 42 | 43 | ```md 44 | Error: listen EADDRINUSE: address already in use :::3000 45 | ``` 46 | 47 | ## Mintlify Versions 48 | 49 | Each CLI is linked to a specific version of Mintlify. Please update the CLI if your local website looks different than production. 50 | 51 | 52 | 53 | ```bash npm 54 | npm i -g mintlify@latest 55 | ``` 56 | 57 | ```bash yarn 58 | yarn global upgrade mintlify 59 | ``` 60 | 61 | 62 | 63 | ## Deployment 64 | 65 | 66 | Unlimited editors available under the [Startup 67 | Plan](https://mintlify.com/pricing) 68 | 69 | 70 | You should see the following if the deploy successfully went through: 71 | 72 | 73 | 74 | 75 | 76 | ## Troubleshooting 77 | 78 | Here's how to solve some common problems when working with the CLI. 79 | 80 | 81 | 82 | Update to Node v18. Run `mintlify install` and try again. 83 | 84 | 85 | Go to the `C:/Users/Username/.mintlify/` directory and remove the `mint` 86 | folder. Then Open the Git Bash in this location and run `git clone 87 | https://github.com/mintlify/mint.git`. 88 | 89 | Repeat step 3. 90 | 91 | 92 | 93 | Try navigating to the root of your device and delete the ~/.mintlify folder. 94 | Then run `mintlify dev` again. 95 | 96 | 97 | 98 | Curious about what changed in a CLI version? [Check out the CLI changelog.](/changelog/command-line) 99 | -------------------------------------------------------------------------------- /docs/essentials/code.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Code Blocks' 3 | description: 'Display inline code and code blocks' 4 | icon: 'code' 5 | --- 6 | 7 | ## Basic 8 | 9 | ### Inline Code 10 | 11 | To denote a `word` or `phrase` as code, enclose it in backticks (`). 12 | 13 | ``` 14 | To denote a `word` or `phrase` as code, enclose it in backticks (`). 15 | ``` 16 | 17 | ### Code Block 18 | 19 | Use [fenced code blocks](https://www.markdownguide.org/extended-syntax/#fenced-code-blocks) by enclosing code in three backticks and follow the leading ticks with the programming language of your snippet to get syntax highlighting. Optionally, you can also write the name of your code after the programming language. 20 | 21 | ```java HelloWorld.java 22 | class HelloWorld { 23 | public static void main(String[] args) { 24 | System.out.println("Hello, World!"); 25 | } 26 | } 27 | ``` 28 | 29 | ````md 30 | ```java HelloWorld.java 31 | class HelloWorld { 32 | public static void main(String[] args) { 33 | System.out.println("Hello, World!"); 34 | } 35 | } 36 | ``` 37 | ```` 38 | -------------------------------------------------------------------------------- /docs/essentials/images.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Images and Embeds' 3 | description: 'Add image, video, and other HTML elements' 4 | icon: 'image' 5 | --- 6 | 7 | 11 | 12 | ## Image 13 | 14 | ### Using Markdown 15 | 16 | The [markdown syntax](https://www.markdownguide.org/basic-syntax/#images) lets you add images using the following code 17 | 18 | ```md 19 | ![title](/path/image.jpg) 20 | ``` 21 | 22 | Note that the image file size must be less than 5MB. Otherwise, we recommend hosting on a service like [Cloudinary](https://cloudinary.com/) or [S3](https://aws.amazon.com/s3/). You can then use that URL and embed. 23 | 24 | ### Using Embeds 25 | 26 | To get more customizability with images, you can also use [embeds](/writing-content/embed) to add images 27 | 28 | ```html 29 | 30 | ``` 31 | 32 | ## Embeds and HTML elements 33 | 34 | 44 | 45 |
46 | 47 | 48 | 49 | Mintlify supports [HTML tags in Markdown](https://www.markdownguide.org/basic-syntax/#html). This is helpful if you prefer HTML tags to Markdown syntax, and lets you create documentation with infinite flexibility. 50 | 51 | 52 | 53 | ### iFrames 54 | 55 | Loads another HTML page within the document. Most commonly used for embedding videos. 56 | 57 | ```html 58 | 59 | ``` 60 | -------------------------------------------------------------------------------- /docs/essentials/markdown.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Markdown Syntax' 3 | description: 'Text, title, and styling in standard markdown' 4 | icon: 'text-size' 5 | --- 6 | 7 | ## Titles 8 | 9 | Best used for section headers. 10 | 11 | ```md 12 | ## Titles 13 | ``` 14 | 15 | ### Subtitles 16 | 17 | Best use to subsection headers. 18 | 19 | ```md 20 | ### Subtitles 21 | ``` 22 | 23 | 24 | 25 | Each **title** and **subtitle** creates an anchor and also shows up on the table of contents on the right. 26 | 27 | 28 | 29 | ## Text Formatting 30 | 31 | We support most markdown formatting. Simply add `**`, `_`, or `~` around text to format it. 32 | 33 | | Style | How to write it | Result | 34 | | ------------- | ----------------- | --------------- | 35 | | Bold | `**bold**` | **bold** | 36 | | Italic | `_italic_` | _italic_ | 37 | | Strikethrough | `~strikethrough~` | ~strikethrough~ | 38 | 39 | You can combine these. For example, write `**_bold and italic_**` to get **_bold and italic_** text. 40 | 41 | You need to use HTML to write superscript and subscript text. That is, add `` or `` around your text. 42 | 43 | | Text Size | How to write it | Result | 44 | | ----------- | ------------------------ | ---------------------- | 45 | | Superscript | `superscript` | superscript | 46 | | Subscript | `subscript` | subscript | 47 | 48 | ## Linking to Pages 49 | 50 | You can add a link by wrapping text in `[]()`. You would write `[link to google](https://google.com)` to [link to google](https://google.com). 51 | 52 | Links to pages in your docs need to be root-relative. Basically, you should include the entire folder path. For example, `[link to text](/writing-content/text)` links to the page "Text" in our components section. 53 | 54 | Relative links like `[link to text](../text)` will open slower because we cannot optimize them as easily. 55 | 56 | ## Blockquotes 57 | 58 | ### Singleline 59 | 60 | To create a blockquote, add a `>` in front of a paragraph. 61 | 62 | > Dorothy followed her through many of the beautiful rooms in her castle. 63 | 64 | ```md 65 | > Dorothy followed her through many of the beautiful rooms in her castle. 66 | ``` 67 | 68 | ### Multiline 69 | 70 | > Dorothy followed her through many of the beautiful rooms in her castle. 71 | > 72 | > The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood. 73 | 74 | ```md 75 | > Dorothy followed her through many of the beautiful rooms in her castle. 76 | > 77 | > The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood. 78 | ``` 79 | 80 | ### LaTeX 81 | 82 | Mintlify supports [LaTeX](https://www.latex-project.org) through the Latex component. 83 | 84 | 8 x (vk x H1 - H2) = (0,1) 85 | 86 | ```md 87 | 8 x (vk x H1 - H2) = (0,1) 88 | ``` 89 | -------------------------------------------------------------------------------- /docs/essentials/navigation.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Navigation' 3 | description: 'The navigation field in mint.json defines the pages that go in the navigation menu' 4 | icon: 'map' 5 | --- 6 | 7 | The navigation menu is the list of links on every website. 8 | 9 | You will likely update `mint.json` every time you add a new page. Pages do not show up automatically. 10 | 11 | ## Navigation syntax 12 | 13 | Our navigation syntax is recursive which means you can make nested navigation groups. You don't need to include `.mdx` in page names. 14 | 15 | 16 | 17 | ```json Regular Navigation 18 | "navigation": [ 19 | { 20 | "group": "Getting Started", 21 | "pages": ["quickstart"] 22 | } 23 | ] 24 | ``` 25 | 26 | ```json Nested Navigation 27 | "navigation": [ 28 | { 29 | "group": "Getting Started", 30 | "pages": [ 31 | "quickstart", 32 | { 33 | "group": "Nested Reference Pages", 34 | "pages": ["nested-reference-page"] 35 | } 36 | ] 37 | } 38 | ] 39 | ``` 40 | 41 | 42 | 43 | ## Folders 44 | 45 | Simply put your MDX files in folders and update the paths in `mint.json`. 46 | 47 | For example, to have a page at `https://yoursite.com/your-folder/your-page` you would make a folder called `your-folder` containing an MDX file called `your-page.mdx`. 48 | 49 | 50 | 51 | You cannot use `api` for the name of a folder unless you nest it inside another folder. Mintlify uses Next.js which reserves the top-level `api` folder for internal server calls. A folder name such as `api-reference` would be accepted. 52 | 53 | 54 | 55 | ```json Navigation With Folder 56 | "navigation": [ 57 | { 58 | "group": "Group Name", 59 | "pages": ["your-folder/your-page"] 60 | } 61 | ] 62 | ``` 63 | 64 | ## Hidden Pages 65 | 66 | MDX files not included in `mint.json` will not show up in the sidebar but are accessible through the search bar and by linking directly to them. 67 | -------------------------------------------------------------------------------- /docs/essentials/reusable-snippets.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Reusable Snippets 3 | description: Reusable, custom snippets to keep content in sync 4 | icon: 'recycle' 5 | --- 6 | 7 | import SnippetIntro from '/snippets/snippet-intro.mdx'; 8 | 9 | 10 | 11 | ## Creating a custom snippet 12 | 13 | **Pre-condition**: You must create your snippet file in the `snippets` directory. 14 | 15 | 16 | Any page in the `snippets` directory will be treated as a snippet and will not 17 | be rendered into a standalone page. If you want to create a standalone page 18 | from the snippet, import the snippet into another file and call it as a 19 | component. 20 | 21 | 22 | ### Default export 23 | 24 | 1. Add content to your snippet file that you want to re-use across multiple 25 | locations. Optionally, you can add variables that can be filled in via props 26 | when you import the snippet. 27 | 28 | ```mdx snippets/my-snippet.mdx 29 | Hello world! This is my content I want to reuse across pages. My keyword of the 30 | day is {word}. 31 | ``` 32 | 33 | 34 | The content that you want to reuse must be inside the `snippets` directory in 35 | order for the import to work. 36 | 37 | 38 | 2. Import the snippet into your destination file. 39 | 40 | ```mdx destination-file.mdx 41 | --- 42 | title: My title 43 | description: My Description 44 | --- 45 | 46 | import MySnippet from '/snippets/path/to/my-snippet.mdx'; 47 | 48 | ## Header 49 | 50 | Lorem impsum dolor sit amet. 51 | 52 | 53 | ``` 54 | 55 | ### Reusable variables 56 | 57 | 1. Export a variable from your snippet file: 58 | 59 | ```mdx snippets/path/to/custom-variables.mdx 60 | export const myName = 'my name'; 61 | 62 | export const myObject = { fruit: 'strawberries' }; 63 | ``` 64 | 65 | 2. Import the snippet from your destination file and use the variable: 66 | 67 | ```mdx destination-file.mdx 68 | --- 69 | title: My title 70 | description: My Description 71 | --- 72 | 73 | import { myName, myObject } from '/snippets/path/to/custom-variables.mdx'; 74 | 75 | Hello, my name is {myName} and I like {myObject.fruit}. 76 | ``` 77 | 78 | ### Reusable components 79 | 80 | 1. Inside your snippet file, create a component that takes in props by exporting 81 | your component in the form of an arrow function. 82 | 83 | ```mdx snippets/custom-component.mdx 84 | export const MyComponent = ({ title }) => ( 85 |
86 |

{title}

87 |

... snippet content ...

88 |
89 | ); 90 | ``` 91 | 92 | 93 | MDX does not compile inside the body of an arrow function. Stick to HTML 94 | syntax when you can or use a default export if you need to use MDX. 95 | 96 | 97 | 2. Import the snippet into your destination file and pass in the props 98 | 99 | ```mdx destination-file.mdx 100 | --- 101 | title: My title 102 | description: My Description 103 | --- 104 | 105 | import { MyComponent } from '/snippets/custom-component.mdx'; 106 | 107 | Lorem ipsum dolor sit amet. 108 | 109 | 110 | ``` 111 | -------------------------------------------------------------------------------- /docs/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/getting-started/setup.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Setup" 3 | sidebarTitle: "Setup" 4 | description: "Create a brand-new folder with packages powered by React Print." 5 | icon: "fa-solid fa-hammer" 6 | --- 7 | # Fast Set Up ⚡️ 8 | 9 | Clone this repository ⬇️ 10 | 15 | Clone our dev-local repository and follow the instructions in the readMe to get started quickly. 16 | 17 | 18 | ![dev-local view](https://github.com/OnedocLabs/dev-local/blob/main/src/images/screenshot-dev-local.png?raw=true) 19 | 20 | 21 | We recommed splitting your editor into two windows, one for the code and the other for the PDF viewing integration. 22 | 23 | 24 | # Manual Set Up 🛠️ 25 | 26 | ## 1. Create directory 27 | 28 | Create a new folder called `react-print-starter` and initialize a new npm project 29 | 30 | ```sh 31 | mkdir react-print-starter 32 | cd react-print-starter 33 | npm init -y 34 | ``` 35 | 36 | ## 2. Install the dependencies 37 | 38 | Get the react-print package locally 39 | 40 | 41 | 42 | ```sh title="npm" 43 | npm install @fileforge/react-print 44 | ``` 45 | 46 | ```sh title="yarn" 47 | yarn add @fileforge/react-print 48 | ``` 49 | 50 | ```sh title="pnpm" 51 | pnpm add @fileforge/react-print 52 | ``` 53 | 54 | 55 | 56 | ## 3. Create your first PDF Component 57 | 58 | Create a new `documents` folder, then create a new file inside called `index.jsx` and copy the following code: 59 | 60 | 61 | ```jsx document/index.tsx 62 | import { PageTop, PageBottom, PageBreak } from "@fileforge/react-print"; 63 | import * as React from "react"; 64 | 65 | export const Document = ({ props }) => { 66 | return ( 67 |
68 | 69 | Hello #1 70 | 71 |
Hello #2
72 | 73 |
Hello #3
74 |
75 | 76 | Hello #4, but on a new page ! 77 |
78 | ); 79 | }; 80 | ``` 81 | 82 | ## 4. Compile your document to HTML 83 | 84 | Back in your parent folder, create a `main.jsx` file that imports your document an renders it using the `compile` function. 85 | 86 | ```js index.tsx 87 | import { compile } from "@fileforge/react-print"; 88 | import { Document } from "./document"; 89 | 90 | const html = await compile(); 91 | 92 | console.log(html); 93 | ``` 94 | 95 | ## 5. Generate your document with FileForge 96 | 97 | We recommend generating your PDF using the [FileForge API](/integrations/onedoc), as it is specifically designed to integrate seamlessly with react-print. However, you are welcome to choose any external renderer that better meets your needs. 98 | [How to generate my PDF from my react-print component.](/api-reference/api-reference/generate) 99 | 100 | ## 6. Next steps 101 | 102 | Try to modify your PDF by using our different pre-built components. 103 | 104 | 105 | 106 | A React component to help compile your React code for PDF rendering. 107 | 108 | 109 | {" "} 110 | 111 | 112 | A React component to help you build beautiful foot-notes. 113 | 114 | 115 | 116 | A suite of React components for structured document layout management. 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/guides/fonts.mdx: -------------------------------------------------------------------------------- 1 | Fonts work the same way as they would in the browser. 2 | 3 | ## Hosted Webfont 4 | 5 | You can add a link to any hosted webfont stylesheet, such as: 6 | 7 | * Google Fonts or Typekit, 8 | * Self-hosted fonts on an existing website. 9 | 10 | To use these fonts when converting to PDF, you will have to link the stylesheet in your HTML. Given that HTML5 supports `` placement in the `` and ``, you can place the link in either location, or inside your React component. 11 | 12 | 13 | 14 | ```html 15 | 16 | 17 | 18 | 19 | 20 | 23 |

Some text

24 | 25 | 26 | ``` 27 |
28 | 29 | ```jsx 30 | const Document = () => { 31 | return ( 32 | <> 33 | 34 |

37 |

38 | 39 | ) 40 | } 41 | ``` 42 |
43 |
44 | 45 | ## Local Webfont 46 | 47 | You can also use local webfonts. To do this, you will need to include the font files as an asset when uploading with the Onedoc SDK. You can then reference the font in your CSS. 48 | 49 | ```css 50 | @font-face { 51 | font-family: 'Roboto'; 52 | src: url('Roboto-Regular.ttf') format('truetype'); 53 | } 54 | ``` 55 | 56 | 57 | 58 | ```ts 59 | const file = ff.pdf.generate([ 60 | new File([fs.readFileSync("index.html")], "index.html", { 61 | type: "text/html", 62 | }), 63 | new File([fs.readFileSync("Roboto-Regular.ttf")], "Roboto-Regular.ttf", { 64 | type: "font/ttf", 65 | }), 66 | ], {}) 67 | ``` 68 | 69 | 70 | ```sh 71 | curl -X POST "https://api.fileforge.com/pdf/generate" \ 72 | -H "X-API-Key: YOUR_API_KEY" \ 73 | -F "files[]=@index.html;type=text/html" \ 74 | -F "files[]=@Roboto-Regular.ttf;type=font/ttf" 75 | ``` 76 | 77 | 78 | -------------------------------------------------------------------------------- /docs/guides/images/toc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/guides/images/toc.jpg -------------------------------------------------------------------------------- /docs/guides/references.mdx: -------------------------------------------------------------------------------- 1 | Fileforge's PDF generation API supports rich cross-referencing capabilities. This allows you to create links between different parts of your document, such as linking to a specific section or page. 2 | 3 | ## Cross-linking 4 | 5 | Similarly to HTML, Fileforge automatically parses local links in your document. 6 | 7 | ```html 8 | Go to section 1 9 | 10 | Go to google.com 11 | 12 |
13 | 14 |
15 | ``` 16 | 17 | This also works in elements contained in the page shell, such as headers and footers. 18 | 19 | 20 | 21 | ```tsx 22 | const Document = () => { 23 | return <> 24 | 25 | Go to first page 26 | 27 |
28 |

Cover page

29 |
30 | 31 | } 32 | ``` 33 |
34 |
35 | 36 | ## Pointers 37 | 38 | ### Counters 39 | 40 | When adding cross-references to PDFs, you may want to consider their printed page number. Fileforge provides a `page` counter that you can use to reference the page number. 41 | 42 | ```html 43 | 48 | 49 | Section 1 50 | 51 | 52 |
53 | 54 |
55 | ``` 56 | 57 | You can also reference custom counters, such as a section number. 58 | 59 | ```html 60 | 77 | 78 | Section 1 79 | 80 | 81 |
82 | 83 |
84 | ``` 85 | 86 | ### Names 87 | 88 | You can also use the contents of a target element to reference it. For example, you may want to display `(see "Cover page")` instead of `(see page 1)`. 89 | 90 | 91 | Since the target content will be inlined, we recommend adding the ID to headers rather than sections or divs. 92 | 93 | 94 | ```html 95 | 100 | 101 | Cover page 102 | 103 |
104 |

Cover page

105 | 106 |
107 | ``` 108 | 109 | ## Example: Table of Contents 110 | 111 | You can combine the above functionality to build a table of contents that automatically updates with the page numbers. 112 | 113 | ```html 114 | 140 | 141 |
    142 |
  • 143 | 144 |
      145 |
    • 146 | 147 |
    • 148 |
    • 149 | 150 |
    • 151 |
    152 |
  • 153 |
  • 154 | 155 |
  • 156 |
157 | 158 |

Introduction

159 | 160 |

This is the first section

161 | 162 |

This is the second section

163 | 164 |

Conclusion

165 | ``` 166 | 167 | This will yeld the following table of contents: 168 | 169 | 170 | ![Table of contents](./images/toc.jpg) 171 | 172 | -------------------------------------------------------------------------------- /docs/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/background.png -------------------------------------------------------------------------------- /docs/images/banner-twitter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/banner-twitter.jpg -------------------------------------------------------------------------------- /docs/images/checks-passed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/checks-passed.png -------------------------------------------------------------------------------- /docs/images/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/example.png -------------------------------------------------------------------------------- /docs/images/legacy-vs-react-print.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/legacy-vs-react-print.avif -------------------------------------------------------------------------------- /docs/images/previews/compile-8dbcfb7e/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/compile-8dbcfb7e/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/compile-8dbcfb7e/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/compile-8dbcfb7e/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/compile-f31067dd/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/compile-f31067dd/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/compile-f31067dd/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/compile-f31067dd/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/css-fa74d9a5/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/css-fa74d9a5/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/css-fa74d9a5/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/css-fa74d9a5/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/currentpagetop-2643a477/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/currentpagetop-2643a477/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/currentpagetop-2643a477/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/currentpagetop-2643a477/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/field-8e7a7bcb/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/field-8e7a7bcb/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/field-8e7a7bcb/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/field-8e7a7bcb/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/floatbottom-1c4af231/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/floatbottom-1c4af231/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/floatbottom-1c4af231/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/floatbottom-1c4af231/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/font-0d283416/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/font-0d283416/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/font-0d283416/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/font-0d283416/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/footnote-e49ec577/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/footnote-e49ec577/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/footnote-e49ec577/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/footnote-e49ec577/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/latex-2663e15e/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/latex-2663e15e/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/latex-2663e15e/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/latex-2663e15e/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/latex-c1cd8f84/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/latex-c1cd8f84/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/latex-c1cd8f84/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/latex-c1cd8f84/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/margins-35fa1266/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/margins-35fa1266/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/margins-35fa1266/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/margins-35fa1266/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/markdown-344947c9/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/markdown-344947c9/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/markdown-344947c9/document.2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/markdown-344947c9/document.2.jpg -------------------------------------------------------------------------------- /docs/images/previews/markdown-344947c9/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/markdown-344947c9/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/markdown-cdc02780/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/markdown-cdc02780/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/markdown-cdc02780/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/markdown-cdc02780/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/markdown-f4432de3/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/markdown-f4432de3/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/markdown-f4432de3/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/markdown-f4432de3/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/nobreak-ba337df4/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/nobreak-ba337df4/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/nobreak-ba337df4/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/nobreak-ba337df4/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/pagebottom-fd5eaff9/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagebottom-fd5eaff9/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/pagebottom-fd5eaff9/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagebottom-fd5eaff9/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/pagebreak-bb162ea2/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagebreak-bb162ea2/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/pagebreak-bb162ea2/document.2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagebreak-bb162ea2/document.2.jpg -------------------------------------------------------------------------------- /docs/images/previews/pagebreak-bb162ea2/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagebreak-bb162ea2/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/pagenumber-4d636b47/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagenumber-4d636b47/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/pagenumber-4d636b47/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagenumber-4d636b47/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/pagenumber-fe8490ef/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagenumber-fe8490ef/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/pagenumber-fe8490ef/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagenumber-fe8490ef/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/pagesnumber-ba7ca0ce/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagesnumber-ba7ca0ce/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/pagesnumber-ba7ca0ce/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagesnumber-ba7ca0ce/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/pagetop-53bf6bd2/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagetop-53bf6bd2/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/pagetop-53bf6bd2/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/pagetop-53bf6bd2/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/runningh1-230ef375/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/runningh1-230ef375/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/runningh1-230ef375/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/runningh1-230ef375/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/tailwind-1aadcc0c/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/tailwind-1aadcc0c/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/tailwind-1aadcc0c/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/tailwind-1aadcc0c/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/tailwind-b7e447a6/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/tailwind-b7e447a6/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/tailwind-b7e447a6/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/tailwind-b7e447a6/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/tailwind-e99fe796/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/tailwind-e99fe796/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/tailwind-e99fe796/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/tailwind-e99fe796/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-invoice-advanced-657df4ea/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-invoice-advanced-657df4ea/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-invoice-advanced-657df4ea/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-invoice-advanced-657df4ea/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-invoice-c1137a92/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-invoice-c1137a92/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-invoice-c1137a92/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-invoice-c1137a92/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.2.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.3.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.4.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.5.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-nda-markdown-a1c048ca/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-receipt-644d535a/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-receipt-644d535a/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-receipt-644d535a/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-receipt-644d535a/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-report-charts-fe27a92e/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-report-charts-fe27a92e/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-report-charts-fe27a92e/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-report-charts-fe27a92e/document.pdf -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-scientific-report-7f68dcf5/document.1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-scientific-report-7f68dcf5/document.1.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-scientific-report-7f68dcf5/document.2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-scientific-report-7f68dcf5/document.2.jpg -------------------------------------------------------------------------------- /docs/images/previews/ui-templates-scientific-report-7f68dcf5/document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/previews/ui-templates-scientific-report-7f68dcf5/document.pdf -------------------------------------------------------------------------------- /docs/images/react-email-cover.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/images/react-email-cover.avif -------------------------------------------------------------------------------- /docs/integrations/onedoc.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Onedoc" 3 | sidebarTitle: "Onedoc" 4 | description: "Use Onedoc as your primary documents generation and management providers" 5 | icon: "1" 6 | --- 7 | 8 | In this section we will show you how can you generate and host a .pdf using [Onedoc's SDK](https://www.npmjs.com/package/@onedoc/client). 9 | 10 | Onedoc is currently in public beta mode. 11 | 12 | ## Prerequisites 13 | 14 | To get the most out of this guide, you'll need to: 15 | 16 | - [Sign-up/in to Onedoc](https://app.onedoclabs.com/login) 17 | - [Generate your API Key](https://app.onedoclabs.com/login) 18 | 19 | ## 1. Installation 20 | 21 | 22 | Want to get started without a project? We have setup a [simple 23 | CodeSandbox](https://codesandbox.io/p/devbox/onedoc-template-invoice-forked-jdyw6j?embed=1&file=%2Findex.tsx) 24 | for you to try out. 25 | 26 | 27 | If you did not have set up a NodeJS project, you can use the following command to do so: 28 | 29 | ```sh npm 30 | npm init -y 31 | ``` 32 | 33 | Get the Onedoc Node.js SDK 34 | 35 | 36 | 37 | ```sh npm 38 | npm install @onedoc/client 39 | ``` 40 | 41 | ```sh yarn 42 | yarn add @onedoc/client 43 | ``` 44 | 45 | ```sh pnpm 46 | pnpm add @onedoc/client 47 | ``` 48 | 49 | 50 | 51 | ## 2. Create a document template 52 | 53 | Create a `components` directory using the following command: 54 | 55 | ```sh terminal 56 | mkdir components 57 | ``` 58 | 59 | Then create your document template on `components/pdf-template.jsx`.
Your file must export a React component. 60 | 61 | ```javascript components/pdf-template.jsx 62 | import * as React from "react"; 63 | 64 | export const PDFTemplate = ({ name }) => { 65 | return ( 66 |
67 |

Hello {name} !

68 |
69 | ); 70 | }; 71 | ``` 72 | 73 | and optionally, a stylesheet named `stylesheet.css`, in the `root` directory: 74 | 75 | ```css ./stylesheet.css 76 | body { 77 | background-color: lightblue; 78 | } 79 | ``` 80 | 81 | ## 3. Generate your PDF 82 | 83 | Create a new file `generate.tsx', import the React document template and generate a PDF using your `ONEDOC_API_KEY` and your main React component. 84 | 85 | 86 | 87 | ```javascript generate.tsx 88 | import React from "react"; 89 | import { PDFTemplate } from "./components/pdf-template"; 90 | import { Onedoc } from "@onedoc/client"; 91 | import { readFileSync, writeFileSync } from "fs"; 92 | import { compile } from "@fileforge/react-print"; 93 | import { join } from "path"; 94 | 95 | const ONEDOC_API_KEY = "####-####-####-####"; // replace with your api key 96 | 97 | (async () => { 98 | const onedoc = new Onedoc(ONEDOC_API_KEY); 99 | 100 | let doc = { 101 | html: await compile(), 102 | title: "Hello", 103 | test: true, // if true, produce a PDF in test mode with a Onedoc's watermark 104 | save: true, // if true, host the document and provide a download link in the console and your Onedoc's dashboard 105 | expiresIn: 30, // the number of day you want to host your document 106 | assets: [ 107 | { 108 | path: "./stylesheet.css", 109 | content: readFileSync(join(process.cwd(), "stylesheet.css")).toString(), 110 | }, 111 | ], 112 | }; 113 | 114 | const { file, link, error, info } = await onedoc.render(doc); 115 | 116 | if (error) { 117 | throw error; 118 | } 119 | 120 | console.log(link); 121 | })(); 122 | ``` 123 | 124 | 125 | 126 | You are almost done ! Run the script using the following command : 127 | 128 | ```sh terminal 129 | npx tsx ./generate.tsx 130 | ``` 131 | 132 | Stylesheets and other referenced assets should be passed in the `asset` parameter. If you are using a framework such as Tailwind, you must submit a compiled stylesheet that can be applied to a HTML file that contains the compiled React component.
133 | 134 | You must upload the content of your asset in string or Buffer format in the `content` field. 135 | 136 | ## 4. Congratulations ! 137 | 138 | You just created your first PDF using Onedoc Node.js + React SDK. You can now access your private [dashboard](https://app.onedoclabs.com/) to preview and download your PDF.
139 | -------------------------------------------------------------------------------- /docs/introduction.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "React Print" 3 | sidebarTitle: "Introduction" 4 | description: "Build PDFs using React and TypeScript." 5 | icon: "hand-wave" 6 | --- 7 | 8 | ## Why ? 9 | 10 | 11 | React Print is meant to help developers design PDFs. It outputs an HTML string 12 | that can be used to generate a PDF using a renderer like the [FileForge 13 | API](/api-reference/api-reference/generate). 14 | 15 | 16 | We believe documents are at the core of communication—invoices, contracts, resumes, brochures, etc. They are the primary method for exchanging information with others professionally. So, why do we continue to use decades-old technology to create them? We believe you deserve better. Document production needs to be modernized. Start today and create your next PDF the same way you build a web app. And yes, this includes automating data integration into your documents. **Say hello to react-print.** 17 | 18 | 23 | Contribute to development and give us a ⭐️ 24 | 25 | 26 | ## Getting Started 27 | 28 | React Print is designed to be incrementally adopted, so you can add it to most codebases in a few minutes. 29 | 30 | 31 | React Print is your go-to library for creating PDFs using React and 32 | TypeScript. It provides a set of components to help you build amazing 33 | documents without having to deal with the mess of creating complex layouts and 34 | maintaining archaic markup. 35 | 36 | 37 | Create a brand-new folder with packages powered by React Print. 38 | 39 | 40 | ## Components 41 | 42 | A set of standard components to help you build amazing documents without having to deal with the mess of creating complex layouts and maintaining archaic markup. 43 | 44 | 45 | Compile a React component to a string with the Onedoc print styles. 46 | 47 | Allows adding CSS to the document while securely parsing and escaping it. 48 | 49 | Create automatically numbered footnotes. 50 | 51 | Render LaTeX formulas right in your React components. 52 | 53 | Render Markdown inside your templates. 54 | 55 | Display content in other page regions. 56 | 57 | Add signature fields to your document. 58 | 59 | A simple, drop-in way to use Tailwind CSS in your components. 60 | 61 | Display dynamic values based on your document, such as page numbers and running headers. 62 | 63 | 64 | Help us increase the number of components and start being an active member of 65 | the react-print community by 66 | [contributing](/react-print/contributing/contributing) 67 | 68 | 69 | # Rendering 70 | 71 | PDFs component created by react-print can be rendered, hosted (and more) with your preferred providers. We recommend using the [FileForge API](/api-reference/api-reference/generate) as it has been specificaly build to work with react-print. 72 | 73 | 74 | 75 | Manage your document using Onedoc 76 | 77 | 78 | Coming soon .. 79 | 80 | 81 | 82 | 83 | ## Authors 84 | 85 | - Auguste L. ([@thisisnotFranck](https://twitter.com/thisisnotfranck)) 86 | - Pierre D. ([@pierre_dge120](https://twitter.com/pedro_dge120)) 87 | - Titouan L. ([@titouan325](https://twitter.com/titouan325)) 88 | -------------------------------------------------------------------------------- /docs/logo/dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/logo/light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/logo/react-print-trim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/logo/react-print-trim.png -------------------------------------------------------------------------------- /docs/logo/react-print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnedocLabs/react-print-pdf/f1023fe7b335f228c85ec3a7c0a151fd3d69e22f/docs/logo/react-print.png -------------------------------------------------------------------------------- /docs/mint.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "React Print", 3 | "schema": "schema.json", 4 | "logo": { 5 | "dark": "/logo/react-print-trim.png", 6 | "light": "/logo/react-print-trim.png", 7 | "href": "https://www.onedoclabs.com/" 8 | }, 9 | "favicon": "/favicon.svg", 10 | "colors": { 11 | "primary": "#ffffff", 12 | "light": "#ffffff", 13 | "background": { 14 | "light": "#FFFFFF", 15 | "dark": "#000000" 16 | }, 17 | "anchors": { 18 | "from": "#101010", 19 | "to": "#606060" 20 | } 21 | }, 22 | "redirects": [ 23 | { 24 | "source": "/:slug*", 25 | "destination": "https://docs.fileforge.com/react-print/:slug*" 26 | } 27 | ], 28 | "seo": { 29 | "indexHiddenPages": true 30 | }, 31 | "analytics": { 32 | "posthog": { 33 | "apiKey": "phc_jHjWg3U3A39knTK6ChWEUHIXMFYZ7rATZOLzhK39dv9", 34 | "apiHost": "https://eu.posthog.com" 35 | }, 36 | "ga4": { 37 | "measurementId": "G-KD443H3TZ3" 38 | } 39 | }, 40 | "modeToggle": { 41 | "default": "dark", 42 | "isHidden": true 43 | }, 44 | "feedback": { 45 | "thumbsRating": true 46 | }, 47 | "topbarLinks": [], 48 | "topbarCtaButton": { 49 | "type": "github", 50 | "url": "https://github.com/OnedocLabs/react-print" 51 | }, 52 | "tabs": [], 53 | "anchors": [ 54 | { 55 | "name": "Documentation", 56 | "icon": "book-open-cover", 57 | "url": "https://react.onedoclabs.com/introduction" 58 | }, 59 | { 60 | "name": "Discord", 61 | "icon": "discord", 62 | "url": "https://discord.gg/uRJE6e2rgr" 63 | }, 64 | { 65 | "name": "Github", 66 | "icon": "github", 67 | "url": "https://github.com/OnedocLabs/react-print" 68 | }, 69 | { 70 | "name": "Onedoc", 71 | "icon": "globe", 72 | "url": "https://www.onedoclabs.com/" 73 | } 74 | ], 75 | "navigation": [ 76 | { 77 | "group": "Overview", 78 | "pages": [ 79 | "introduction", 80 | "contributing" 81 | ] 82 | }, 83 | { 84 | "group": "Getting Started", 85 | "pages": [ 86 | "getting-started/setup" 87 | ] 88 | }, 89 | { 90 | "group": "Integrations", 91 | "pages": [ 92 | "integrations/onedoc" 93 | ] 94 | }, 95 | { 96 | "group": "Components", 97 | "pages": [ 98 | "/react-print/components/undefined", 99 | "/react-print/components/undefined", 100 | "/react-print/components/undefined", 101 | "/react-print/components/undefined", 102 | "/react-print/components/undefined", 103 | "/react-print/components/undefined", 104 | "/react-print/components/undefined", 105 | "/react-print/components/undefined", 106 | "/react-print/components/undefined" 107 | ] 108 | }, 109 | { 110 | "group": "Templates", 111 | "pages": [ 112 | "ui/templates", 113 | { 114 | "group": "Reports", 115 | "pages": [ 116 | "ui/templates/scientific-report", 117 | "ui/templates/report-charts" 118 | ] 119 | }, 120 | { 121 | "group": "Receipts", 122 | "pages": [ 123 | "ui/templates/receipt" 124 | ] 125 | }, 126 | { 127 | "group": "NDA", 128 | "pages": [ 129 | "ui/templates/nda-markdown" 130 | ] 131 | }, 132 | { 133 | "group": "Invoices", 134 | "pages": [ 135 | "ui/templates/invoice", 136 | "ui/templates/invoice-advanced" 137 | ] 138 | } 139 | ] 140 | }, 141 | { 142 | "group": "Troubleshooting", 143 | "pages": [ 144 | "troubleshooting/faq" 145 | ] 146 | } 147 | ], 148 | "footerSocials": { 149 | "twitter": "https://twitter.com/Onedoclabs", 150 | "github": "https://github.com/OnedocLabs/onedoc", 151 | "linkedin": "https://www.linkedin.com/company/onedoclabs" 152 | } 153 | } -------------------------------------------------------------------------------- /docs/quickstart.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Quickstart' 3 | description: 'Start building awesome documentation in under 5 minutes' 4 | --- 5 | 6 | ## Setup your development 7 | 8 | Learn how to update your docs locally and and deploy them to the public. 9 | 10 | ### Edit and preview 11 | 12 | 13 | 14 | During the onboarding process, we created a repository on your Github with 15 | your docs content. You can find this repository on our 16 | [dashboard](https://dashboard.mintlify.com). To clone the repository 17 | locally, follow these 18 | [instructions](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) 19 | in your terminal. 20 | 21 | 22 | Previewing helps you make sure your changes look as intended. We built a 23 | command line interface to render these changes locally. 1. Install the 24 | [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the 25 | documentation changes locally with this command: ``` npm i -g mintlify ``` 26 | 2. Run the following command at the root of your documentation (where 27 | `mint.json` is): ``` mintlify dev ``` 28 | 29 | 30 | 31 | ### Deploy your changes 32 | 33 | 34 | 35 | 36 | Our Github app automatically deploys your changes to your docs site, so you 37 | don't need to manage deployments yourself. You can find the link to install on 38 | your [dashboard](https://dashboard.mintlify.com). Once the bot has been 39 | successfully installed, there should be a check mark next to the commit hash 40 | of the repo. 41 | 42 | 43 | [Commit and push your changes to 44 | Git](https://docs.github.com/en/get-started/using-git/pushing-commits-to-a-remote-repository#about-git-push) 45 | for your changes to update in your docs site. If you push and don't see that 46 | the Github app successfully deployed your changes, you can also manually 47 | update your docs through our [dashboard](https://dashboard.mintlify.com). 48 | 49 | 50 | 51 | 52 | ## Update your docs 53 | 54 | Add content directly in your files with MDX syntax and React components. You can use any of our components, or even build your own. 55 | 56 | 57 | 58 | 59 | Add flair to your docs with personalized branding. 60 | 61 | 62 | 67 | Implement your OpenAPI spec and enable API user interaction. 68 | 69 | 70 | 75 | Draw insights from user interactions with your documentation. 76 | 77 | 78 | 83 | Keep your docs on your own website's subdomain. 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/snippets/components.mdx: -------------------------------------------------------------------------------- 1 | 2 | Compile a React component to a string with the Onedoc print styles. 3 | 4 | Allows adding CSS to the document while securely parsing and escaping it. 5 | 6 | Create automatically numbered footnotes. 7 | 8 | Render LaTeX formulas right in your React components. 9 | 10 | Render Markdown inside your templates. 11 | 12 | Display content in other page regions. 13 | 14 | Add signature fields to your document. 15 | 16 | A simple, drop-in way to use Tailwind CSS in your components. 17 | 18 | Display dynamic values based on your document, such as page numbers and running headers. 19 | -------------------------------------------------------------------------------- /docs/troubleshooting/faq.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: "FAQ" 3 | --- 4 | 5 | ## Issues with Node.js modules 6 | 7 | `react-print` ships both for server and client side. Some components are only available for the server side such as `Tailwind`. 8 | 9 | If you plan to use `react-print` on the client side, you should import your components from `@fileforge/react-print/client` instead of `@fileforge/react-print` or `@fileforge/react-print/server`. 10 | -------------------------------------------------------------------------------- /docs/ui/templates.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Browse 3 | icon: list 4 | --- 5 | 6 | ## Reports 7 | 8 | 9 | 10 |
11 | 12 |
13 |
14 | 15 |
16 | 17 |
18 |
19 |
20 | 21 | ## Receipts 22 | 23 | 24 | 25 |
26 | 27 |
28 |
29 |
30 | 31 | ## NDA 32 | 33 | 34 | 35 |
36 | 37 |
38 |
39 |
40 | 41 | ## Invoices 42 | 43 | 44 | 45 |
46 | 47 |
48 |
49 | 50 |
51 | 52 |
53 |
54 |
55 | 56 | -------------------------------------------------------------------------------- /docs/ui/templates/receipt.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Receipt 3 | icon: receipt 4 | category: Receipts 5 | --- 6 | 7 | 8 | 9 | ```jsx 10 | import { Footnote, Tailwind } from "@fileforge/react-print"; 11 | 12 | 13 |
14 |
15 |
16 |
17 |
18 | 27 | 28 | 33 | 34 | 35 | 36 |

37 | Receipt from Acme Inc. 38 |

39 |

Receipt #10192

40 |
41 |
42 |
43 |
44 | Amount paid 45 |
46 |
$12.99
47 |
48 |
49 |
50 | Date 51 |
52 |
Feb 8th, 2024
53 |
54 |
55 |
56 | Payment method 57 |
58 |
59 | 67 | 73 | 78 | 84 | 85 | 0911 86 |
87 |
88 |
89 |

90 | Summary 91 |

92 |
93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 |
Basic Pro Plan$12.99
Amount charged$12.99
103 |
104 |
105 | This is some additional content to to inform you that Acme Inc. is a 106 | fake company and this is a fake receipt. This is just a demo to show you 107 | how you can create a beautiful receipt with Onedoc.{" "} 108 | 109 | Some additional conditions may apply. This template comes from the 110 | react-print library, available at https://react.onedoclabs.com/ 111 | 112 |
113 |
114 |
115 | ; 116 | 117 | ``` 118 | 119 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@fileforge/react-print", 3 | "version": "0.1.150", 4 | "description": "Fileforge components for JavaScript React", 5 | "main": "./dist/index.js", 6 | "module": "./dist/index.mjs", 7 | "types": "./dist/index.d.ts", 8 | "exports": { 9 | ".": { 10 | "require": "./dist/index.js", 11 | "import": "./dist/index.mjs", 12 | "types": "./dist/index.d.ts" 13 | }, 14 | "./client": { 15 | "require": "./dist/client/index.js", 16 | "import": "./dist/client/index.mjs", 17 | "types": "./dist/client/index.d.ts" 18 | }, 19 | "./server": { 20 | "require": "./dist/server/index.js", 21 | "import": "./dist/server/index.mjs", 22 | "types": "./dist/server/index.d.ts" 23 | }, 24 | "./mdx": { 25 | "require": "./dist/mdx.js", 26 | "import": "./dist/mdx.mjs", 27 | "types": "./dist/mdx.d.ts" 28 | }, 29 | "./dist/*.css": { 30 | "import": "./dist/*.css", 31 | "require": "./dist/*.css" 32 | } 33 | }, 34 | "scripts": { 35 | "build": "patch-package && tsup --external @fileforge/react-print --clean && tsup --external @fileforge/react-print", 36 | "test": "vitest --browser chrome", 37 | "dev": "(cd ./docs && mintlify dev --watch)", 38 | "build-components": "npm run build && tsx ./docgen/index.ts", 39 | "prune-docs": "tsx ./docgen/prune.ts", 40 | "build-components-commit": "npm run build-components && npm run prune-docs" 41 | }, 42 | "pre-commit": [ 43 | "build-components-commit" 44 | ], 45 | "author": "", 46 | "license": "ISC", 47 | "devDependencies": { 48 | "@chakra-ui/react": "^2.8.2", 49 | "@esbuild-plugins/node-modules-polyfill": "^0.2.2", 50 | "@heroicons/react": "^2.1.1", 51 | "@mdx-js/esbuild": "^3.0.0", 52 | "@mhsdesign/jit-browser-tailwindcss": "^0.3.0", 53 | "@onedoc/client": "^0.1.28", 54 | "@swc/core": "^1.3.107", 55 | "@tailwindcss/typography": "^0.5.10", 56 | "@types/postcss-css-variables": "^0.18.3", 57 | "@types/react": "^18.2.55", 58 | "@types/react-dom": "^18.2.18", 59 | "@vitest/browser": "^1.4.0", 60 | "acorn": "^8.11.3", 61 | "acorn-typescript": "^1.4.13", 62 | "autoprefixer": "^10.4.17", 63 | "dotenv": "^16.4.1", 64 | "esbuild-plugin-alias": "^0.2.1", 65 | "front-matter": "^4.0.2", 66 | "mintlify": "^4.0.122", 67 | "node-stdlib-browser": "^1.2.0", 68 | "patch-package": "^8.0.0", 69 | "pdf2pic": "^3.1.1", 70 | "postcss": "^8.4.35", 71 | "postcss-color-functional-notation": "^6.0.4", 72 | "postcss-css-variables": "^0.19.0", 73 | "postcss-logical": "^7.0.1", 74 | "pre-commit": "^1.2.2", 75 | "prettier": "^3.2.5", 76 | "qrcode.react": "^3.1.0", 77 | "react-docgen-typescript": "^2.2.2", 78 | "recharts": "^2.12.0", 79 | "remark-frontmatter": "^5.0.0", 80 | "tsup": "^8.0.1", 81 | "tsx": "^4.7.0", 82 | "typescript": "^5.3.3", 83 | "vitest": "^1.3.1", 84 | "webdriverio": "^8.34.1" 85 | }, 86 | "dependencies": { 87 | "@csstools/postcss-is-pseudo-class": "^4.0.8", 88 | "@emotion/cache": "^11.11.0", 89 | "@emotion/react": "^11.11.3", 90 | "@emotion/server": "^11.11.0", 91 | "html-entities": "^2.4.0", 92 | "katex": "^0.16.9", 93 | "markdown-to-jsx": "^7.4.1", 94 | "react": "^18.2.0", 95 | "react-dom": "^18.2.0", 96 | "tailwindcss": "3.3.2" 97 | }, 98 | "optionalDependencies": { 99 | "@rollup/rollup-linux-x64-gnu": "^4.11.0" 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /patches/@mhsdesign+jit-browser-tailwindcss+0.3.0.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/@mhsdesign/jit-browser-tailwindcss/package.json b/node_modules/@mhsdesign/jit-browser-tailwindcss/package.json 2 | index 1bc9e7b..01067a3 100644 3 | --- a/node_modules/@mhsdesign/jit-browser-tailwindcss/package.json 4 | +++ b/node_modules/@mhsdesign/jit-browser-tailwindcss/package.json 5 | @@ -11,6 +11,13 @@ 6 | "index.d.ts", 7 | "dist/*" 8 | ], 9 | + "exports": { 10 | + ".": { 11 | + "require": "./dist/module.esm.js", 12 | + "import": "./dist/module.esm.js" 13 | + }, 14 | + "./dist/*": "./dist/*" 15 | + }, 16 | "type": "module", 17 | "scripts": { 18 | "prepack": "node build.js", 19 | -------------------------------------------------------------------------------- /src/client.ts: -------------------------------------------------------------------------------- 1 | import "./generic.css"; 2 | 3 | export { 4 | RunningH1, 5 | RunningH2, 6 | RunningH3, 7 | RunningH4, 8 | RunningH5, 9 | RunningH6, 10 | PageNumber, 11 | PagesNumber, 12 | } from "./variables/variables"; 13 | export { 14 | PageBottom, 15 | PageBreak, 16 | PageTop, 17 | CurrentPageTop, 18 | NoBreak, 19 | FloatBottom, 20 | } from "./shell/shell"; 21 | export { Footnote } from "./footnote/footnote"; 22 | export { compile, CompileOptions } from "./compile/compile"; 23 | export { CSS, Font, Margins } from "./css/css"; 24 | export { Markdown } from "./markdown/markdown"; 25 | export { Latex } from "./latex/latex"; 26 | export { Tailwind } from "./tailwind/tailwind"; 27 | export { Field } from "./signature/signature"; 28 | -------------------------------------------------------------------------------- /src/compile/compile.tsx: -------------------------------------------------------------------------------- 1 | import { DocConfig } from "docgen/types"; 2 | import React from "react"; 3 | import { Button, ChakraProvider } from "@chakra-ui/react"; 4 | 5 | // @ts-ignore 6 | import onedocStyles from "../../dist/index.css?raw"; 7 | 8 | import { CSS } from "../css/css"; 9 | import { Tailwind } from "../tailwind/tailwind"; 10 | 11 | export interface CompileOptions { 12 | /** 13 | * Whether to use Emotion CSS. 14 | */ 15 | emotion?: boolean; 16 | } 17 | 18 | export const compile = async ( 19 | node: React.ReactElement, 20 | options?: CompileOptions 21 | ) => { 22 | const { emotion } = Object.assign( 23 | { 24 | emotion: false, 25 | }, 26 | options || {} 27 | ); 28 | 29 | const ReactDOMServer = await import("react-dom/server"); 30 | 31 | let Element = ( 32 | <> 33 | {onedocStyles} 34 | {node} 35 | 36 | ); 37 | 38 | if (!emotion) { 39 | return ReactDOMServer.renderToString(Element); 40 | } 41 | 42 | const { CacheProvider } = await import("@emotion/react"); 43 | const { default: createCache } = await import("@emotion/cache"); 44 | const { default: createEmotionServer } = await import( 45 | "@emotion/server/create-instance" 46 | ); 47 | 48 | const cache = createCache({ key: "css" }); 49 | const { extractCriticalToChunks, constructStyleTagsFromChunks } = 50 | createEmotionServer(cache); 51 | 52 | Element = {Element}; 53 | 54 | const html = ReactDOMServer.renderToString(Element); 55 | 56 | const chunks = extractCriticalToChunks(html); 57 | const styles = constructStyleTagsFromChunks(chunks); 58 | const mergedStylesheet = styles.replace( 59 | /<\/?style( data-emotion="[a-z0-9- ]+")?>/gm, 60 | "" 61 | ); 62 | 63 | const { default: postcss } = await import("postcss"); 64 | const { default: cssvariables } = await import("postcss-css-variables"); 65 | const { default: isPseudoClass } = await import( 66 | // @ts-ignore 67 | "@csstools/postcss-is-pseudo-class" 68 | ); 69 | // @ts-ignore 70 | const { default: logical } = await import("postcss-logical"); 71 | 72 | const result = await postcss([ 73 | cssvariables(), 74 | logical(), 75 | isPseudoClass(), 76 | ]).process(mergedStylesheet, { 77 | from: undefined, 78 | }); 79 | 80 | return `${html}`; 81 | }; 82 | 83 | export const __docConfig: DocConfig = { 84 | name: "compile", 85 | icon: "fa-solid fa-code", 86 | description: 87 | "Compile a React component to a string with the Onedoc print styles.", 88 | components: { 89 | compile: { 90 | server: true, 91 | client: true, 92 | examples: { 93 | default: { 94 | description: `A simple function to compile a React component to an HTML string with the Onedoc print styles. 95 | \`\`\`jsx 96 | const html = await compile(); 97 | \`\`\``, 98 | template: ( 99 | 100 |
Hello World!
101 |
102 | ), 103 | }, 104 | emotion: { 105 | description: `Pass \`{ emotion: true }\` as the second compile option to merge and extract critical CSS using Emotion. Some libraries such as Chakra UI require this option to work correctly. 106 | 107 | \`\`\`jsx 108 | const html = await compile(, { emotion: true }); 109 | \`\`\``, 110 | template: ( 111 | <> 112 | 113 | 114 | 115 | 116 | ), 117 | name: "Emotion CSS", 118 | compileOptions: { 119 | emotion: true, 120 | }, 121 | externalImports: [ 122 | `import { Button, ChakraProvider, extendTheme } from "@chakra-ui/react";`, 123 | ], 124 | }, 125 | }, 126 | }, 127 | }, 128 | }; 129 | -------------------------------------------------------------------------------- /src/css/css.tsx: -------------------------------------------------------------------------------- 1 | import { DocConfig } from "docgen/types"; 2 | import React from "react"; 3 | import { encode } from "html-entities"; 4 | const allowedEntities = { 5 | "'": "'", 6 | """: '"', 7 | ">": ">", 8 | ":where": ":is", // This may introduce specificity issues, but there is no workaround supported by the engine. 9 | }; 10 | 11 | export const CSS = ({ children }: { children: string }) => { 12 | let contents = encode(children); 13 | 14 | // Replace allowed entities (nb: match all entities and replace them) 15 | for (const [entity, value] of Object.entries(allowedEntities)) { 16 | contents = contents.replace(new RegExp(entity, "g"), value); 17 | } 18 | 19 | return