├── .eslintrc ├── .github └── workflows │ └── update-react-pdf.yml ├── .gitignore ├── LICENSE ├── README.md ├── app ├── error.js ├── globals.css ├── layout.js ├── page.js ├── repl.js ├── robots.js ├── sandpack │ ├── example │ │ ├── Document.jsx │ │ ├── index.html │ │ ├── index.jsx │ │ ├── package.json │ │ ├── styles.css │ │ └── vite.config.js │ ├── global-styles.js │ ├── layout.js │ └── page.js └── sitemap.js ├── code ├── default-example.js └── lz.js ├── components ├── box-sizing.js ├── box-sizing.module.css ├── debug-tree.js ├── debug-tree.module.css ├── elements-tree.js ├── elements-tree.module.css ├── repl-layout.js ├── repl-layout.module.css ├── viewer.js └── viewer.module.css ├── hooks └── index.js ├── next.config.js ├── package-lock.json ├── package.json ├── pages └── api │ ├── g-template.png │ └── og.js ├── patches └── pdfjs-dist+3.3.122.patch ├── public ├── favicon.ico ├── favicon.svg └── og.png ├── state ├── debugger.js └── page.js └── worker ├── better-static-module-record.mjs ├── executer.js ├── index.js ├── process-jsx.js └── to-module.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next", "next/core-web-vitals"] 3 | } 4 | -------------------------------------------------------------------------------- /.github/workflows/update-react-pdf.yml: -------------------------------------------------------------------------------- 1 | name: Autoupdate 2 | on: 3 | schedule: 4 | - cron: "40 11 * * *" 5 | concurrency: 6 | group: "${{ github.workflow }} @ ${{ github.ref }}" 7 | cancel-in-progress: true 8 | jobs: 9 | autoupdate: 10 | runs-on: ubuntu-latest 11 | timeout-minutes: 10 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-node@v3 15 | - name: Update react-pdf 16 | run: npm update @react-pdf/renderer 17 | - name: Update react-pdf 18 | run: npm update @react-pdf/renderer 19 | - name: Commit and push 20 | uses: EndBug/add-and-commit@v9 21 | with: 22 | default_author: github_actions 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright 2023 Dmitry Ivakhnenko 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-pdf-repl 2 | 3 | REPL for `@react-pdf/renderer` with interactive debugger 4 | 5 | ## Examples 6 | 7 | | [![][context_example_image]][context_example] react context usage| [![][emoji_example_image]][emoji_example] emojis | 8 | |:---:|:---:| 9 | | [![][presence_example_image]][presence_example] minPresenceAhead| [![][dimensions_example_image]][dimensions_example] margin padding and border | 10 | | [![][watermark_example_image]][watermark_example] watermark| [![][tailwind_example_image]][tailwind_example] react-pdf and tailwind | 11 | | [![][image_fallback_example_image]][image_fallback_example] image fallback| [![][exif_bug_example_image]][exif_bug_example] exif bug | 12 | 13 | [Create new doc](https://react-pdf-repl.vercel.app/new) 14 | 15 | [context_example]: https://react-pdf-repl.vercel.app/?gz_code=eJzlVWtP2zAU_d5fcRdtUiqVpOU11LXVgME2adMQMKSBkDCJ01pK4sh2oSzKf9-9zqNpeWj7tmkVJY7vw-eee3wrkkwqA3kH4Mw8xPxsxrnp4dsHGcwTntr1CZtyel4Ifk_Pc76w-8eS7AVESibgvFecBWYjCyNf8TTkiivnXUdUB0CAZsMPMYSiYa6X68OZiEOM6UEQy5QfxZxOhjqxzYupOnSep_hUaMOVS5gjloj4YQjOt4yncMZS7RAwrQLcmxmT6aHvRximvak2zIjAC2Tia1-iv0Z3_27w1k94sveDfdSDzd2v4jI72N_4fnxx2eeeMRHmK7p4diBTbUATRxrGLbK8sjAL51aGCIZWABkLQ5FOhzDoE6RiJc85u43r-jHbCjduvu6IHi4S2LCkxU8EUXRhPAEXc4_a6bwTJe8E0g93LJ7zcZ7X_sXEAhtRG8tKyHgrFTofSGNkgmB71capmM4MvlNYXh9djHwKpjwj_8lDJ50l9lN5v4q8gkz8lB4NNPRbCsJtZ8Z0ACIC95V17YKZKcx7pJRUroMcVykyJTMwsiIMm5yhklLj2HjFzVyllqtH9UcxX3wQigdGyBRVg9mdhiuAvBanl7DMXfagXPZAoNIXVFblDysarr3KQocl1isbc41sVDHdogTWkIugi4bGQx7HTymgLQAKtDnqsqrMjQidHdShvRv0oZqHcNOHPrzOKVfx5qa2le0_lxmJYWXvC49Ms1kQ5kpQNA9WRGI3OsuKSBN8YQdByCM2jw24S_D1qGn1BHt__PhqLyVME8mSMHb2tx2QSmA8ow6OnZiloQ5Yxp06YXlrPbqdTV_XVMBiMU0_G55oPJHo2cBxoUxbCfU9K5s4zq92e4B_m3s92OrT97rlis4o__Y77lAnJ4ORb59PmDafN209b9p-3rTz2DTy13D9nzg_4T8J91LFYfkrw8BQc_8R-C_Q_OeV_VXwX6D59ytbg1_9VjVXv5mztKZRUs6qeg6V8-oX3nOE4Q&modules=true 16 | 17 | [context_example_image]: https://react-pdf-repl.vercel.app/api/og?gz_code=eJzlVWtP2zAU_d5fcRdtUiqVpOU11LXVgME2adMQMKSBkDCJ01pK4sh2oSzKf9-9zqNpeWj7tmkVJY7vw-eee3wrkkwqA3kH4Mw8xPxsxrnp4dsHGcwTntr1CZtyel4Ifk_Pc76w-8eS7AVESibgvFecBWYjCyNf8TTkiivnXUdUB0CAZsMPMYSiYa6X68OZiEOM6UEQy5QfxZxOhjqxzYupOnSep_hUaMOVS5gjloj4YQjOt4yncMZS7RAwrQLcmxmT6aHvRximvak2zIjAC2Tia1-iv0Z3_27w1k94sveDfdSDzd2v4jI72N_4fnxx2eeeMRHmK7p4diBTbUATRxrGLbK8sjAL51aGCIZWABkLQ5FOhzDoE6RiJc85u43r-jHbCjduvu6IHi4S2LCkxU8EUXRhPAEXc4_a6bwTJe8E0g93LJ7zcZ7X_sXEAhtRG8tKyHgrFTofSGNkgmB71capmM4MvlNYXh9djHwKpjwj_8lDJ50l9lN5v4q8gkz8lB4NNPRbCsJtZ8Z0ACIC95V17YKZKcx7pJRUroMcVykyJTMwsiIMm5yhklLj2HjFzVyllqtH9UcxX3wQigdGyBRVg9mdhiuAvBanl7DMXfagXPZAoNIXVFblDysarr3KQocl1isbc41sVDHdogTWkIugi4bGQx7HTymgLQAKtDnqsqrMjQidHdShvRv0oZqHcNOHPrzOKVfx5qa2le0_lxmJYWXvC49Ms1kQ5kpQNA9WRGI3OsuKSBN8YQdByCM2jw24S_D1qGn1BHt__PhqLyVME8mSMHb2tx2QSmA8ow6OnZiloQ5Yxp06YXlrPbqdTV_XVMBiMU0_G55oPJHo2cBxoUxbCfU9K5s4zq92e4B_m3s92OrT97rlis4o__Y77lAnJ4ORb59PmDafN209b9p-3rTz2DTy13D9nzg_4T8J91LFYfkrw8BQc_8R-C_Q_OeV_VXwX6D59ytbg1_9VjVXv5mztKZRUs6qeg6V8-oX3nOE4Q&modules=true 18 | 19 | 20 | [emoji_example]: https://react-pdf-repl.vercel.app/?gz_code=eJy1Uk1Lw0AQvfdXDEEhhTTbUuwhpkXxAwQPQsWrxuwkWUl2w-7GVkP-hHjqpSdB_50_wV2baqGCXrwMs2_m7b43s6wohdRQw6ng2oNLnJt4EaXowRXDmQfHIq4K5BoaSKQowDmQGMW6V9KESOQUJUpnv9OxfF9iypRGeVKIOzYVlYzRrTsAtxXLTWcAbiwodmE8MSDATaZ1qQJCYsr9O0UxZ_fS56hJmhGVVZTxlCR5ZZ6vWA_tpb2KM3sHiZRCrchObU--FudihvIoUuh2m-sh9Uue3nidpmuk4fzTI8UkqnINrn0fXKMgXJtbyQmtb1DsEcfO4chZgQa2g2hzAKUfchzX9RcAkBjrU8MKYDjyNvAMWZrpAJxBv7_rbFbKiFpvAQz2NuEoZyk_01goQ4qNLjPa73rTtOnkCwrtvibvy8UrvC-f3rbD4jUknz1blJ-62_A75fllHf6T8mdhf7YfErvLdtvErtvmIfn-B-a_fACFSBSn&modules=true 21 | 22 | [emoji_example_image]: https://react-pdf-repl.vercel.app/api/og?gz_code=eJy1Uk1Lw0AQvfdXDEEhhTTbUuwhpkXxAwQPQsWrxuwkWUl2w-7GVkP-hHjqpSdB_50_wV2baqGCXrwMs2_m7b43s6wohdRQw6ng2oNLnJt4EaXowRXDmQfHIq4K5BoaSKQowDmQGMW6V9KESOQUJUpnv9OxfF9iypRGeVKIOzYVlYzRrTsAtxXLTWcAbiwodmE8MSDATaZ1qQJCYsr9O0UxZ_fS56hJmhGVVZTxlCR5ZZ6vWA_tpb2KM3sHiZRCrchObU--FudihvIoUuh2m-sh9Uue3nidpmuk4fzTI8UkqnINrn0fXKMgXJtbyQmtb1DsEcfO4chZgQa2g2hzAKUfchzX9RcAkBjrU8MKYDjyNvAMWZrpAJxBv7_rbFbKiFpvAQz2NuEoZyk_01goQ4qNLjPa73rTtOnkCwrtvibvy8UrvC-f3rbD4jUknz1blJ-62_A75fllHf6T8mdhf7YfErvLdtvErtvmIfn-B-a_fACFSBSn&modules=true 23 | 24 | [presence_example]: https://react-pdf-repl.vercel.app/?gz_code=eJy9U01v00AQvedXjNxLKrl2PmiJQhzRFgVxQFRqqUQRh8UeJ4u8Xmd33A8s_3dmYydOCIgb8sHrmeeZeW_eSlVoQ1DBHT6TDzdiiT7cS3zy4Z2OS4U5Rxc6J6ghNVqB99agiOmsSNLQYJ6gQeO96fUcJjC4lJbQ9KseQCqUzF6m4H0qMIdbkVvP57A1McdWRIWdhmHKv9lgaUmQjINYq9CGmvGW4eHj8HWoUE2-iPd2OLr4KB-Kq8uzz4v7hwEGRCnXq0-5d6xzS3AtTAIR9CtYoeC5fOA4oRv9FKI59Ln5zFEDSy8ZRlUFTzKh1RRGg4EPhUgSmS-ncA51PWcso50omxOAkvmNQYt5jJeuflSNz-s2t63XfjJ1bnwrfyKXfuXvom2HK02kFffpMsR97gxTTrXhjFcWBZpYWPQ6TKwzbTh3MplMduG6GWHeflYN8yY4C934e0w63t18wwu_q4wj93iOf9VqV3dVZqETb95ziuPzxjYJpqLMCPqdwFvXHDZbHHuhU9mZroMf7AEsTxlVX8duQ7ymb_WW6maTO3GONgDwo7Qk05frhge3jvnFXvX3MCKTy_wDobJ_ytfb_c53oZkz2V6BRu_IW2GWaTgZenu5VsHIu8cMHnVWFiTs9sA9QdC6RAezuC4FlQbQGG0g19-lDfgWkkBAbSFxC-IfUJhSOSdKJQK-se7uMoJgXUoLuVzJDJTOkIkLG3SzhPPeIYPf5-ad76b9Z9njcn8XZPwfBTng207XWrY5O581Rt6adGPmX0O6fjQ&modules=true 25 | 26 | [presence_example_image]: https://react-pdf-repl.vercel.app/api/og?gz_code=eJy9U01v00AQvedXjNxLKrl2PmiJQhzRFgVxQFRqqUQRh8UeJ4u8Xmd33A8s_3dmYydOCIgb8sHrmeeZeW_eSlVoQ1DBHT6TDzdiiT7cS3zy4Z2OS4U5Rxc6J6ghNVqB99agiOmsSNLQYJ6gQeO96fUcJjC4lJbQ9KseQCqUzF6m4H0qMIdbkVvP57A1McdWRIWdhmHKv9lgaUmQjINYq9CGmvGW4eHj8HWoUE2-iPd2OLr4KB-Kq8uzz4v7hwEGRCnXq0-5d6xzS3AtTAIR9CtYoeC5fOA4oRv9FKI59Ln5zFEDSy8ZRlUFTzKh1RRGg4EPhUgSmS-ncA51PWcso50omxOAkvmNQYt5jJeuflSNz-s2t63XfjJ1bnwrfyKXfuXvom2HK02kFffpMsR97gxTTrXhjFcWBZpYWPQ6TKwzbTh3MplMduG6GWHeflYN8yY4C934e0w63t18wwu_q4wj93iOf9VqV3dVZqETb95ziuPzxjYJpqLMCPqdwFvXHDZbHHuhU9mZroMf7AEsTxlVX8duQ7ymb_WW6maTO3GONgDwo7Qk05frhge3jvnFXvX3MCKTy_wDobJ_ytfb_c53oZkz2V6BRu_IW2GWaTgZenu5VsHIu8cMHnVWFiTs9sA9QdC6RAezuC4FlQbQGG0g19-lDfgWkkBAbSFxC-IfUJhSOSdKJQK-se7uMoJgXUoLuVzJDJTOkIkLG3SzhPPeIYPf5-ad76b9Z9njcn8XZPwfBTng207XWrY5O581Rt6adGPmX0O6fjQ&modules=true 27 | 28 | [dimensions_example]: https://react-pdf-repl.vercel.app/?gz_code=eJyVVl1vmzAUfc-vuGKallQkQCjdlCXZ2lXdHjZtartWa9UHCoZYChgZZ0kX5b_vmo8AaSBBPIDtc--5Pj7XggYR4wLWcEtWQoVftk9UuKNkqcIlcxYBCXH2ioUCNuBxFoDymRPbEf3I9TROQpdwwpWPnY7EDDjxaSwI7647AJ4d0PnLCJSfEQnhxg5jRcXpmDs4NxMiikea5mFYPPBjYQvqDBwWaLHGEB8jXPtrvNcCEnz4Y3-NjeHZD_oQXZz3f1_dPehkIISH-TY95HZYGAvwibhgHAuCCXSfky8VKFa4wgm9B5Mpsp9zbr8MaJy8M1QPPkH6NbBFN4nAqfIcRo9ggQseDYm7ZbxgMnV3DZHtujT0VQhs7tNQhZw-pv8IbCQ3dJF9LJXFN4BLnhd-8hWLlzmZrNfJALapsmGWMBulab-wOeOo4RsylI9SXb1l0T11xWxUCLJVQ-9VsdfUn4latLGDvmBCsKAWPtyBfydefW5zC16mEKnUp8GjoitPUnsjX54RWWOxblTWNxt8adNO4YJrtkzPxJnRuYsO3ZV_Kzj4djQCQ1fBm5PVJeXEEZSFKCxnSyWdvecSoyzxpSDZNCFd56kl-ViTScsVfCN2ZsL9RchOK4qQDXCDe8NKzlQQuHbL0fse4wESL6KIcMeOScJeEI81mSVlJaukhdGc9mIuoFsw5R1cZbt63ZfbrY3lBZBoPVHOz5QiMLPlCMwtFtHpVqfZ4ljLxvkynkX-jSPZLRlyohi6ktKsHy08AUt_2shz3A8e6tAKb75tAZa5ARnMVgxJCAY2BY21kgC5VmlDHyFVCqwoZSKFua-uHFsVSsKNJnhJJ3OIqYcN2D0yGYfKQXnAgr5VaGSpcGod1Ci9JI7QKAUmpWDSQ6e3RQ8TYfDGygVqiFxrJyB7ENtItobLSBy-w47CzsSuIy5eUJzAibap4TLbFFaqy2y1I8NKI_HVGLffknRF3FaOlLavNFClCw54wigHV1rIrNtnYdgdZqva6QccbEkPG1aZPpmydmo4baqhj2h8-s1ppNOtzOm1nsXDSo9N8tXreZRncivvV_YIB-3UcMwdWme_Jl2O2U-WzbDKueqyNHm0TqR2Zq07sXaurb2rjjXtgWY_aNzUtYlxD90bJfO-ujfGmvxHmCa_PvkPRvIj8h_5n2bA&modules=true 29 | 30 | [dimensions_example_image]: https://react-pdf-repl.vercel.app/api/og?gz_code=eJyVVl1vmzAUfc-vuGKallQkQCjdlCXZ2lXdHjZtartWa9UHCoZYChgZZ0kX5b_vmo8AaSBBPIDtc--5Pj7XggYR4wLWcEtWQoVftk9UuKNkqcIlcxYBCXH2ioUCNuBxFoDymRPbEf3I9TROQpdwwpWPnY7EDDjxaSwI7647AJ4d0PnLCJSfEQnhxg5jRcXpmDs4NxMiikea5mFYPPBjYQvqDBwWaLHGEB8jXPtrvNcCEnz4Y3-NjeHZD_oQXZz3f1_dPehkIISH-TY95HZYGAvwibhgHAuCCXSfky8VKFa4wgm9B5Mpsp9zbr8MaJy8M1QPPkH6NbBFN4nAqfIcRo9ggQseDYm7ZbxgMnV3DZHtujT0VQhs7tNQhZw-pv8IbCQ3dJF9LJXFN4BLnhd-8hWLlzmZrNfJALapsmGWMBulab-wOeOo4RsylI9SXb1l0T11xWxUCLJVQ-9VsdfUn4latLGDvmBCsKAWPtyBfydefW5zC16mEKnUp8GjoitPUnsjX54RWWOxblTWNxt8adNO4YJrtkzPxJnRuYsO3ZV_Kzj4djQCQ1fBm5PVJeXEEZSFKCxnSyWdvecSoyzxpSDZNCFd56kl-ViTScsVfCN2ZsL9RchOK4qQDXCDe8NKzlQQuHbL0fse4wESL6KIcMeOScJeEI81mSVlJaukhdGc9mIuoFsw5R1cZbt63ZfbrY3lBZBoPVHOz5QiMLPlCMwtFtHpVqfZ4ljLxvkynkX-jSPZLRlyohi6ktKsHy08AUt_2shz3A8e6tAKb75tAZa5ARnMVgxJCAY2BY21kgC5VmlDHyFVCqwoZSKFua-uHFsVSsKNJnhJJ3OIqYcN2D0yGYfKQXnAgr5VaGSpcGod1Ci9JI7QKAUmpWDSQ6e3RQ8TYfDGygVqiFxrJyB7ENtItobLSBy-w47CzsSuIy5eUJzAibap4TLbFFaqy2y1I8NKI_HVGLffknRF3FaOlLavNFClCw54wigHV1rIrNtnYdgdZqva6QccbEkPG1aZPpmydmo4baqhj2h8-s1ppNOtzOm1nsXDSo9N8tXreZRncivvV_YIB-3UcMwdWme_Jl2O2U-WzbDKueqyNHm0TqR2Zq07sXaurb2rjjXtgWY_aNzUtYlxD90bJfO-ujfGmvxHmCa_PvkPRvIj8h_5n2bA&modules=true 31 | 32 | [watermark_example]: https://react-pdf-repl.vercel.app/?gz_code=eJytVluP4jYUfudXHKVbCdoJiZ0bzADqVtVc1KWtNFvU8tL1EkOiyU1JyMwU8d_72UC4zG6flmBsn_v5fHJMnBZ5WdOmQ_RRvtRXmB-blZr-EHWk5rvdZiXVPIvls5p_yRfrVGZa_kOcPan5Nlf7LS3LPCXjp1KKRW0W4dIqZRbKUpbGTaejhPqlXMVVLcuucrsUaZy8XpPxeyEzehRZZShrVbkALarrorq2rCXUqv6qqkUdL_qLPLUqK4d8BXGrYYGVynTwt7irGPen8bz4-b355-1sbst-XS9hb9uD70WeVTU9C3hORfmkEqQxXBlTn7hPjILISxxiDjkmcyL_ZO0lpkdsGJl-YoLATZcYv_fnUyeAamQ6icnxMBMqenDCLnKEPyR8bf24JkuYqR4emW5iMsh4JhMBBZrPIOFFgXIrfPL3NE5egwhMrzEd4ZG3I8MJaM485VjBFShq8EbZZoLp0HeSHEYc29NDB6KCbxAKTIM3n_qcgsa999gsiBibp-YQYfgNG0KERax1qqKxQXMFAxjHQGydzT7_GZ9PAxegJCo3gAW4FHamDyQdAi1yxYAGh4zJUxYbgBkgQfhHBtpYCxFG4-hoMSI3YftsPZ2bMqpk59OBOgqk4EGa7w7gxBEnu8EpQhH4JAoU4cL7DhCYaRgY3nzKbHZuBvFDbgeW2rvtfncu_oypQPf5cx0abxhi8k452ushnYMvZ3BRPYDgELsqngH5g68Uj5Jxv1A8_Kx4nG9RPHxg6_HF4mGe8wavr8DO_w_2APZw9qjAxMcvymdAzNaoQQFFiehnDGXJPWA-Txkso8IG8OfSkBTewdxo3_ICDesx_lfSmFw27HvOzZ4RovMoon3TkS-694VyKdZJTd0ejSfURUMYHdobVfVrIsebDakGdPu2U9F2O4ECVFSHpAoex8Z739gRQVYNc7-m1lpLIIpkvIpq2GS2_b1ufIdPIcIwzlbXxO1TskjiVfZQy7SC0gIxoq-e8leiOFfZbvfLSUsaqVY_uZdJktNzXiYhAZsatkaW5nSOkqq5U1TK5bjtxau4jtafdRMOY7nK03UprGO3B8CLdVXFQNvizPeMyUl0H-8fHgnfDw-__Xp0YikvLWSWwqyNQSNIy_hFhsfTKPIqruEBEIjPVZ6sa3k8Cq2FS4ye47COxgYfBn3fNfZQjzeH0sBNFSfJ2MjyTJ4FuXlfluK1r-6x7gkZDEpktqqja5ri7uiX-ToLu22lWbq2evQj3rrt1Zli958rinV5xSf0Xj8VRbf7JF_byjt-RndnWyKIjTf42V7Q6xKFuMzLdLz5VOa4IGUXF1RvR0_09p3Sox-Iudvi5YrebS5MaOPgq_gvWFDofTp3ObkQGemLNBxvzm7WA7rf2bZtUF6IRVwjAbvveFuy3ti4O8nDaEP_q8ttGxEYl_LfyKt1d066IPR625MiRUld1uhurV59tR5Zh74x6eD_xn9ik03x&modules=true 33 | 34 | [watermark_example_image]: https://react-pdf-repl.vercel.app/api/og?gz_code=eJytVluP4jYUfudXHKVbCdoJiZ0bzADqVtVc1KWtNFvU8tL1EkOiyU1JyMwU8d_72UC4zG6flmBsn_v5fHJMnBZ5WdOmQ_RRvtRXmB-blZr-EHWk5rvdZiXVPIvls5p_yRfrVGZa_kOcPan5Nlf7LS3LPCXjp1KKRW0W4dIqZRbKUpbGTaejhPqlXMVVLcuucrsUaZy8XpPxeyEzehRZZShrVbkALarrorq2rCXUqv6qqkUdL_qLPLUqK4d8BXGrYYGVynTwt7irGPen8bz4-b355-1sbst-XS9hb9uD70WeVTU9C3hORfmkEqQxXBlTn7hPjILISxxiDjkmcyL_ZO0lpkdsGJl-YoLATZcYv_fnUyeAamQ6icnxMBMqenDCLnKEPyR8bf24JkuYqR4emW5iMsh4JhMBBZrPIOFFgXIrfPL3NE5egwhMrzEd4ZG3I8MJaM485VjBFShq8EbZZoLp0HeSHEYc29NDB6KCbxAKTIM3n_qcgsa999gsiBibp-YQYfgNG0KERax1qqKxQXMFAxjHQGydzT7_GZ9PAxegJCo3gAW4FHamDyQdAi1yxYAGh4zJUxYbgBkgQfhHBtpYCxFG4-hoMSI3YftsPZ2bMqpk59OBOgqk4EGa7w7gxBEnu8EpQhH4JAoU4cL7DhCYaRgY3nzKbHZuBvFDbgeW2rvtfncu_oypQPf5cx0abxhi8k452ushnYMvZ3BRPYDgELsqngH5g68Uj5Jxv1A8_Kx4nG9RPHxg6_HF4mGe8wavr8DO_w_2APZw9qjAxMcvymdAzNaoQQFFiehnDGXJPWA-Txkso8IG8OfSkBTewdxo3_ICDesx_lfSmFw27HvOzZ4RovMoon3TkS-694VyKdZJTd0ejSfURUMYHdobVfVrIsebDakGdPu2U9F2O4ECVFSHpAoex8Z739gRQVYNc7-m1lpLIIpkvIpq2GS2_b1ufIdPIcIwzlbXxO1TskjiVfZQy7SC0gIxoq-e8leiOFfZbvfLSUsaqVY_uZdJktNzXiYhAZsatkaW5nSOkqq5U1TK5bjtxau4jtafdRMOY7nK03UprGO3B8CLdVXFQNvizPeMyUl0H-8fHgnfDw-__Xp0YikvLWSWwqyNQSNIy_hFhsfTKPIqruEBEIjPVZ6sa3k8Cq2FS4ye47COxgYfBn3fNfZQjzeH0sBNFSfJ2MjyTJ4FuXlfluK1r-6x7gkZDEpktqqja5ri7uiX-ToLu22lWbq2evQj3rrt1Zli958rinV5xSf0Xj8VRbf7JF_byjt-RndnWyKIjTf42V7Q6xKFuMzLdLz5VOa4IGUXF1RvR0_09p3Sox-Iudvi5YrebS5MaOPgq_gvWFDofTp3ObkQGemLNBxvzm7WA7rf2bZtUF6IRVwjAbvveFuy3ti4O8nDaEP_q8ttGxEYl_LfyKt1d066IPR625MiRUld1uhurV59tR5Zh74x6eD_xn9ik03x&modules=true 35 | 36 | [tailwind_example]: https://react-pdf-repl.vercel.app/?gz_code=eJyNVNtuG0cMffdXEHqSkL1IRtAUrmTUReC8JE0ApwGaIChGs9w1k7llLlq5gv69nNXFllyg3QdpLuTh4SE5pJ31ETbw2sqk0cQCPogOC_iIa15_IuwLuLUmwhZabzWMfvUoZCxd09YeTYMe_eiXCzrgSL6O-LE_2h_NyyhI9WQaNr_IkJXHjkJEP95cALRCk3q4gtF7hwbuhAmjgo-Dl3x2H6MLV3XdsluouhBFJFlJq-tQW7YPbF6vZq9qjfrnP8WbMLv86R19dr_dlH_cfvo8xSrGlvG2E44trQkRYg-LI9uBQbxHjVeQlwCcPmd32AFIq6wPj3s-SSFazeSk9aZVtke_VAkH1vnb7hbD33YfGteDTA22IqkIbTIykjVw49x4MmB7jMkbGA--80NVIMQHhYvNBrICt8-lgu32eh93ngsIgf7Gxejm5ejgGvvxyJUvoVW4Hn5Kb_vdovfCQSf4djQ5wgBsvlRVdeO9eBjPLidfKy3cePxXATSBxfWe4T5k7pMne4Dv-LDY0Pbk7AmRIewMNJmyL79cTqcufoUDu5K1hmVXZjXL2XTKpE5wMt3FphUq4NOL6xOjeW7gpyEj78vLtRoULJdWNTAc7cp4kvjuu8NdbTYEL2B2SmFeZ_j_EzH8G_Rb61EDuZA0NLmxuFwRhEYeudydHDm3AYiGHAVJpgNUFCv4PSklzsACaocesG1JUvZStERvgQwowYGQ_e6wARIyKQoFaNEZASExsKN4huaUkOhFZB5a28YW4IlNgYGZCkQykprEHamoS0oUICRgosC28C1L-ZwdULMD2fPXR4cVhkjLpFgGhRxKW8UMmeCaNMcMwhGaM0CVZOQ7MhW_TiuR7bRQGJJoBKyScokfBwSeSeGxgncicWxILK_kWeKH4gyvZWXDIxYa0sATyJnxhHqSyGcJWNDACAUsWVzTMOEV3hMLel6NbFjBBy8w5Lnd1dh6SUN2OV-EzosVMVuG5_2PhCC48A1nu0zhDG9FUSCwH4Pei4BKMUmFgwYmq7nvmB-Ja8ZENXGuBbe2ds-wXFIrYlnAsDlW_9HR8zpP9ePJ5DiG8zo_MbubeX14o_Ke37jtxT9q3-Z8&modules=true 37 | 38 | [tailwind_example_image]: https://react-pdf-repl.vercel.app/api/og?gz_code=eJyNVNtuG0cMffdXEHqSkL1IRtAUrmTUReC8JE0ApwGaIChGs9w1k7llLlq5gv69nNXFllyg3QdpLuTh4SE5pJ31ETbw2sqk0cQCPogOC_iIa15_IuwLuLUmwhZabzWMfvUoZCxd09YeTYMe_eiXCzrgSL6O-LE_2h_NyyhI9WQaNr_IkJXHjkJEP95cALRCk3q4gtF7hwbuhAmjgo-Dl3x2H6MLV3XdsluouhBFJFlJq-tQW7YPbF6vZq9qjfrnP8WbMLv86R19dr_dlH_cfvo8xSrGlvG2E44trQkRYg-LI9uBQbxHjVeQlwCcPmd32AFIq6wPj3s-SSFazeSk9aZVtke_VAkH1vnb7hbD33YfGteDTA22IqkIbTIykjVw49x4MmB7jMkbGA--80NVIMQHhYvNBrICt8-lgu32eh93ngsIgf7Gxejm5ejgGvvxyJUvoVW4Hn5Kb_vdovfCQSf4djQ5wgBsvlRVdeO9eBjPLidfKy3cePxXATSBxfWe4T5k7pMne4Dv-LDY0Pbk7AmRIewMNJmyL79cTqcufoUDu5K1hmVXZjXL2XTKpE5wMt3FphUq4NOL6xOjeW7gpyEj78vLtRoULJdWNTAc7cp4kvjuu8NdbTYEL2B2SmFeZ_j_EzH8G_Rb61EDuZA0NLmxuFwRhEYeudydHDm3AYiGHAVJpgNUFCv4PSklzsACaocesG1JUvZStERvgQwowYGQ_e6wARIyKQoFaNEZASExsKN4huaUkOhFZB5a28YW4IlNgYGZCkQykprEHamoS0oUICRgosC28C1L-ZwdULMD2fPXR4cVhkjLpFgGhRxKW8UMmeCaNMcMwhGaM0CVZOQ7MhW_TiuR7bRQGJJoBKyScokfBwSeSeGxgncicWxILK_kWeKH4gyvZWXDIxYa0sATyJnxhHqSyGcJWNDACAUsWVzTMOEV3hMLel6NbFjBBy8w5Lnd1dh6SUN2OV-EzosVMVuG5_2PhCC48A1nu0zhDG9FUSCwH4Pei4BKMUmFgwYmq7nvmB-Ja8ZENXGuBbe2ds-wXFIrYlnAsDlW_9HR8zpP9ePJ5DiG8zo_MbubeX14o_Ke37jtxT9q3-Z8&modules=true 39 | 40 | [image_fallback_example]: https://react-pdf-repl.vercel.app/?gz_code=eJzFVF1v0zAUfe-vsPrUSU3cDhisrBVjrF0RaNM6htjL5CROYohjy75Zu1X571w76ceYeES8xLnX9-Pcc08ipFYGyLpDyFSV0MdzAY8FX-Sce-uTiivJm5srlnF33gq-dOdcto4bvsKAmqRGSdL9YDiLIdBJSg0vE2646b7vdFz90PBMWOCm5zqmTIricUS6l5qXZMFK23XVrInRlwNoO6I0xTQbZhYYiDiMlaSWKoy3GE4fhm-p5PLdDzazw8Ojr-JOfzwNvk1v7wY8BEixXn2AvWNVWiDWTWbJeG_EMEawwD2cSCUIxr0RolmSiDIbkcNB3zsypkdk6I263_HgiyJi8S9PwjZNWQFClYifRVYVFfBukw8K89taBU9haxiR5TsrUgBKbs2nOfK3GpFg2Dbem8Y3_i4gn7ZIcDA_B_LX3wO4MDHebPkUoZBZZTyT8Hqmj09vwp868zCXIoHcveTcoXLtyHhCeug5cUtvGByv121kG0fqeuLhnnhMDsB4jY-a0Enn2UWT3uwhfMZg3WTtgfbZmEpd50nHDc5XXq0JT1lVAOnt0G1kukPodDN9KbAd1quXiJwC2msMcKqeVKWttOvKE3JxPj8jwk_S2wAlwhKbq2V5cEJ9wib7xXrai5bl8fpwMKi3vobIP5yOkd13IBAhk9rh9F9B8049Hor5cesahs7otlU2G9jM8_nqfPaPke4r7Dor-MPFNPIS-wuks8vrBapVFP-B1VWQpEHEbBp4fkEZrB9I5v5RCQMWaKOS0L4KeRXEqC_DimAYMsmeVMmWzSY8JktnRi0hx_8UruPLNY2YKfjjfRTF-f2b41CX-_P7WahTYCPxjXy9zH8DOrGvNw&modules=true 41 | 42 | [image_fallback_example_image]: https://react-pdf-repl.vercel.app/api/og?gz_code=eJzFVF1v0zAUfe-vsPrUSU3cDhisrBVjrF0RaNM6htjL5CROYohjy75Zu1X571w76ceYeES8xLnX9-Pcc08ipFYGyLpDyFSV0MdzAY8FX-Sce-uTiivJm5srlnF33gq-dOdcto4bvsKAmqRGSdL9YDiLIdBJSg0vE2646b7vdFz90PBMWOCm5zqmTIricUS6l5qXZMFK23XVrInRlwNoO6I0xTQbZhYYiDiMlaSWKoy3GE4fhm-p5PLdDzazw8Ojr-JOfzwNvk1v7wY8BEixXn2AvWNVWiDWTWbJeG_EMEawwD2cSCUIxr0RolmSiDIbkcNB3zsypkdk6I263_HgiyJi8S9PwjZNWQFClYifRVYVFfBukw8K89taBU9haxiR5TsrUgBKbs2nOfK3GpFg2Dbem8Y3_i4gn7ZIcDA_B_LX3wO4MDHebPkUoZBZZTyT8Hqmj09vwp868zCXIoHcveTcoXLtyHhCeug5cUtvGByv121kG0fqeuLhnnhMDsB4jY-a0Enn2UWT3uwhfMZg3WTtgfbZmEpd50nHDc5XXq0JT1lVAOnt0G1kukPodDN9KbAd1quXiJwC2msMcKqeVKWttOvKE3JxPj8jwk_S2wAlwhKbq2V5cEJ9wib7xXrai5bl8fpwMKi3vobIP5yOkd13IBAhk9rh9F9B8049Hor5cesahs7otlU2G9jM8_nqfPaPke4r7Dor-MPFNPIS-wuks8vrBapVFP-B1VWQpEHEbBp4fkEZrB9I5v5RCQMWaKOS0L4KeRXEqC_DimAYMsmeVMmWzSY8JktnRi0hx_8UruPLNY2YKfjjfRTF-f2b41CX-_P7WahTYCPxjXy9zH8DOrGvNw&modules=true 43 | 44 | [exif_bug_example]: https://react-pdf-repl.vercel.app/?gz_code=eJzVlV1LwzAUhu_3Kw4BYYOu2dSpzHUoiiB4IQh6KVl62masTUlSujn63z3Z5j4E7-1VkvP5nDcXR-WlNg7W8KhllWPhAngVKQbwrrAO4DnfPN7caoFvGaKDBhKjc2B3BoV0_TJOuMEiRoOG3XY6UhfWgfXxFqKjxFBSgsPuugMw0_FqTD1LEceqSMcwHEATkEP5dt5Tq9hl3j4IQM_mKN2TcmNgVN4JVTAf3vSoHy43_DEmolo46PYgmkKXSk1-BprSg55-qi1XtN7ihR6jAau-MGL3I7YNpFA_-u4OPynrvQEgWeDyURmCUrogKKNrFvzyfxhRkqum48SXevNwcGzKUKWZH46mPTsJ3utzcZIwr6xTyeqBtKD5vCp0kPyHmKbZXad702TzlUdVTrXYKN8cu42MWOZcacecG1GHqXJZNassGrltHEqd09_LypCN41IlfW0UOYTXpY9LkZdUmufCEh1_EUVspSjxcxDOy5Tte_F_CTlsA-R5GyAv2gB52QbIURsgr9oAed0GyJs_ICfcb6jdXuN-sfn7hB82Hm3Gb-Mva9Q&modules=true 45 | 46 | [exif_bug_example_image]: https://react-pdf-repl.vercel.app/api/og?gz_code=eJzVlV1LwzAUhu_3Kw4BYYOu2dSpzHUoiiB4IQh6KVl62masTUlSujn63z3Z5j4E7-1VkvP5nDcXR-WlNg7W8KhllWPhAngVKQbwrrAO4DnfPN7caoFvGaKDBhKjc2B3BoV0_TJOuMEiRoOG3XY6UhfWgfXxFqKjxFBSgsPuugMw0_FqTD1LEceqSMcwHEATkEP5dt5Tq9hl3j4IQM_mKN2TcmNgVN4JVTAf3vSoHy43_DEmolo46PYgmkKXSk1-BprSg55-qi1XtN7ihR6jAau-MGL3I7YNpFA_-u4OPynrvQEgWeDyURmCUrogKKNrFvzyfxhRkqum48SXevNwcGzKUKWZH46mPTsJ3utzcZIwr6xTyeqBtKD5vCp0kPyHmKbZXad702TzlUdVTrXYKN8cu42MWOZcacecG1GHqXJZNassGrltHEqd09_LypCN41IlfW0UOYTXpY9LkZdUmufCEh1_EUVspSjxcxDOy5Tte_F_CTlsA-R5GyAv2gB52QbIURsgr9oAed0GyJs_ICfcb6jdXuN-sfn7hB82Hm3Gb-Mva9Q&modules=true 47 | -------------------------------------------------------------------------------- /app/error.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { log } from "next-axiom/dist/logger"; 4 | import { useEffect } from "react"; 5 | 6 | export default function Error({ error, reset }) { 7 | useEffect(() => { 8 | log.error(error.message, { error }); 9 | }, [error]); 10 | 11 | return ( 12 |
13 |

Something went wrong!

14 | 15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /app/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 7 | 8 | height: 100%; 9 | } 10 | 11 | body > div#__next { 12 | height: 100%; 13 | } 14 | 15 | a { 16 | color: inherit; 17 | text-decoration: none; 18 | } 19 | 20 | * { 21 | box-sizing: border-box; 22 | } 23 | -------------------------------------------------------------------------------- /app/layout.js: -------------------------------------------------------------------------------- 1 | import { Analytics } from "@vercel/analytics/react"; 2 | 3 | import "./globals.css"; 4 | 5 | export default function RootLayout(props) { 6 | return ( 7 | 8 | 9 | {props.children} 10 | 11 | 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /app/page.js: -------------------------------------------------------------------------------- 1 | import Repl from "./repl"; 2 | 3 | export async function generateMetadata({ searchParams }) { 4 | const cpCode = searchParams && searchParams.cp_code; 5 | const gzCode = searchParams && searchParams.gz_code; 6 | 7 | const ogUrl = new URL("https://react-pdf-repl.vercel.app/api/og"); 8 | 9 | if (cpCode) { 10 | ogUrl.searchParams.append("cp_code", cpCode); 11 | } else if (gzCode) { 12 | ogUrl.searchParams.append("gz_code", gzCode); 13 | } 14 | 15 | /** @type {import('next').Metadata} */ 16 | const metadata = { 17 | title: "PDF repl", 18 | description: "Create and debug PDF files with react", 19 | keywords: [ 20 | "PDF", 21 | "create PDF in browser", 22 | "@react-pdf/renderer", 23 | "react-pdf", 24 | "pdf repl", 25 | ], 26 | robots: "index, follow", 27 | referrer: "origin", 28 | icons: "/favicon.svg", 29 | openGraph: { 30 | type: "website", 31 | url: "https://react-pdf-repl.vercel.app/", 32 | title: "PDF repl", 33 | description: "Create and debug PDF files with react", 34 | images: [ 35 | { 36 | url: ogUrl.toString(), 37 | }, 38 | ], 39 | }, 40 | twitter: { 41 | card: "summary_large_image", 42 | title: "PDF repl", 43 | description: "Create and debug PDF files with react", 44 | creator: "Dmitry Ivakhnenko ", 45 | images: ogUrl.toString(), 46 | }, 47 | alternates: { canonical: "https://react-pdf-repl.vercel.app/" }, 48 | verification: { 49 | google: "2bziNAAYpAHDvCHHUiSzPFk2dEtXm4kLetSFMyAJuyU", 50 | yandex: "36d69e4ea21041e0", 51 | }, 52 | }; 53 | 54 | return metadata; 55 | } 56 | 57 | export default function Component(props) { 58 | return ; 59 | } 60 | -------------------------------------------------------------------------------- /app/repl.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { lazy, useEffect, useReducer, useRef, useState } from "react"; 4 | import Editor from "@monaco-editor/react"; 5 | import useConstant from "use-constant"; 6 | import { useAtom } from "jotai/react"; 7 | import { log } from "next-axiom/dist/logger"; 8 | 9 | import { Panel as ResizablePanel, PanelGroup } from "react-resizable-panels"; 10 | 11 | import { createSingleton, useSetState } from "../hooks"; 12 | import { Worker } from "../worker"; 13 | import Tree from "../components/elements-tree"; 14 | import BoxSizing from "../components/box-sizing"; 15 | import { 16 | Buttons, 17 | Version, 18 | ResizeHandle, 19 | ScrollBox, 20 | DebugFont, 21 | DebugInfo, 22 | Styles, 23 | BoxInfo, 24 | PreviewPanel, 25 | HeaderControls, 26 | FooterControls, 27 | EmptyDebugger, 28 | Preview, 29 | Error, 30 | GithubButton, 31 | } from "../components/repl-layout"; 32 | import { loader } from "../components/viewer.module.css"; 33 | import { 34 | page, 35 | pagesCount, 36 | canDecrease, 37 | canIncrease, 38 | increase, 39 | decrease, 40 | } from "../state/page"; 41 | 42 | import { layoutAtom, selectedAtom } from "../state/debugger"; 43 | 44 | import { decompress, gzCompress, gzDecompress } from "../code/lz"; 45 | import { code as defCode } from "../code/default-example"; 46 | 47 | const Viewer = lazy(() => import("../components/viewer")); 48 | 49 | const useWorker = createSingleton( 50 | () => (typeof document !== "undefined" ? new Worker() : null), 51 | (worker) => worker?.terminate() 52 | ); 53 | 54 | function useMediaQuery(query) { 55 | const getMatches = (query) => { 56 | if (typeof window !== "undefined") { 57 | return window.matchMedia(query).matches; 58 | } 59 | return false; 60 | }; 61 | 62 | const [matches, setMatches] = useState(() => getMatches(query)); 63 | 64 | useEffect(() => { 65 | function handleChange() { 66 | setMatches(getMatches(query)); 67 | } 68 | 69 | const matchMedia = window.matchMedia(query); 70 | 71 | // Triggered at the first client-side load and if query changes 72 | handleChange(); 73 | 74 | matchMedia.addEventListener("change", handleChange); 75 | 76 | return () => { 77 | matchMedia.removeEventListener("change", handleChange); 78 | }; 79 | }, [query]); 80 | 81 | return matches; 82 | } 83 | 84 | const ClientOnly = ({ children }) => { 85 | const [isClient, set] = useState(false); 86 | 87 | useEffect(() => set(true), []); 88 | 89 | return isClient ? children : null; 90 | }; 91 | 92 | const Loader = () =>
; 93 | 94 | const addId = (node, parent, prefix, postfix) => { 95 | if (parent) node.parent = parent; 96 | node._id = [prefix, node.type, postfix].filter((v) => v).join("__"); 97 | 98 | if (node.children) 99 | node.children.forEach((child, index) => { 100 | addId(child, node, node._id, index + 1); 101 | }); 102 | 103 | return node; 104 | }; 105 | 106 | const createLink = (options) => { 107 | const link = new URL(window.location); 108 | 109 | link.searchParams.set("gz_code", gzCompress(options.code)); 110 | 111 | if (options.modules) { 112 | link.searchParams.set("modules", options.modules); 113 | } 114 | 115 | return link.toString(); 116 | }; 117 | 118 | const Repl = () => { 119 | const urlParams = useConstant(() => { 120 | if (typeof window === "undefined") return {}; 121 | 122 | return Object.fromEntries( 123 | Array.from(new URLSearchParams(window.location.search).entries()).map( 124 | ([key, value]) => { 125 | if (key.startsWith("cp_")) { 126 | return [key.slice(3), decompress(value)]; 127 | } 128 | if (key.startsWith("gz_")) { 129 | return [key.slice(3), gzDecompress(value)]; 130 | } 131 | 132 | return [key, value]; 133 | } 134 | ) 135 | ); 136 | }); 137 | 138 | const isMobile = useMediaQuery("(max-width: 600px)"); 139 | 140 | const [options, updateOptions] = useSetState(() => ({ 141 | modules: urlParams.code ? Boolean(urlParams.modules) : true, 142 | })); 143 | 144 | const timeout = useRef(20_000); 145 | 146 | const [state, update] = useSetState(() => ({ 147 | url: null, 148 | version: null, 149 | time: null, 150 | error: null, 151 | isDebuggingSupported: options.modules, 152 | isDebugging: true, 153 | isEditing: true, 154 | })); 155 | 156 | const [isReady, setReady] = useState(false); 157 | const [code, setCode] = useState(() => urlParams.code ?? defCode); 158 | const [v, forceRender] = useReducer((v) => !v); 159 | 160 | const [pageV] = useAtom(page); 161 | const [, setPagesCount] = useAtom(pagesCount); 162 | const [canDecreaseV] = useAtom(canDecrease); 163 | const [, decreaseS] = useAtom(decrease); 164 | const [canIncreaseV] = useAtom(canIncrease); 165 | const [, increaseS] = useAtom(increase); 166 | 167 | const [layout, setLayout] = useAtom(layoutAtom); 168 | const [selectedNode] = useAtom(selectedAtom); 169 | 170 | const pdf = useWorker(); 171 | 172 | const debuggerAPI = useRef(); 173 | const editorPanelAPI = useRef(); 174 | 175 | useEffect(() => { 176 | if (isReady) { 177 | pdf.call("version").then(({ version, isDebuggingSupported }) => 178 | update({ 179 | version, 180 | isDebuggingSupported: options.modules && isDebuggingSupported, 181 | }) 182 | ); 183 | } else { 184 | pdf.call("init").then(() => setReady(true)); 185 | } 186 | }, [pdf, update, isReady, options.modules]); 187 | 188 | useEffect(() => { 189 | if (isReady) { 190 | const startTime = Date.now(); 191 | pdf 192 | .call("evaluate", { 193 | code, 194 | options: { modules: options.modules }, 195 | timeout: timeout.current, 196 | }) 197 | .then(({ url, layout }) => { 198 | if (layout) { 199 | setLayout(addId(layout)); 200 | } else { 201 | setLayout(null); 202 | } 203 | update({ url, time: Date.now() - startTime, error: null }); 204 | }) 205 | .catch((error) => { 206 | if (error.fatal) { 207 | log.error(error.message, { 208 | link: createLink({ code, ...options }), 209 | }); 210 | } 211 | update({ time: Date.now() - startTime, error }); 212 | }); 213 | } 214 | }, [pdf, code, update, isReady, setLayout, options, v]); 215 | 216 | const editorPanel = ( 217 | update({ isEditing: !collapsed })} 223 | > 224 | } 226 | language="javascript" 227 | value={code} 228 | onChange={(newCode) => { 229 | setCode(newCode ?? ""); 230 | }} 231 | beforeMount={(_monaco) => { 232 | _monaco.languages.typescript.javascriptDefaults.setCompilerOptions({ 233 | allowNonTsExtensions: true, 234 | checkJs: true, 235 | allowJs: true, 236 | noLib: true, 237 | jsx: "react", 238 | }); 239 | _monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions( 240 | { noSemanticValidation: true } 241 | ); 242 | }} 243 | options={{ 244 | wordWrap: "on", 245 | tabSize: 2, 246 | minimap: { 247 | enabled: false, 248 | }, 249 | contextmenu: false, 250 | }} 251 | /> 252 | 253 | ); 254 | 255 | const viewerPanel = ( 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | {pageV && ( 264 |
265 | 268 |
275 | page: 276 |
277 | {pageV} 278 |
279 |
280 | 283 |
284 | )} 285 | 286 | 287 | 296 | 297 | 304 | 305 | 306 | 307 |
308 | 309 | 310 | 311 | setPagesCount(pagesCount)} 317 | /> 318 | 319 | 320 | {state.error && ( 321 | { 327 | pdf.start(); 328 | forceRender(); 329 | }, 330 | ], 331 | 332 | [ 333 | "increase timeout and restart", 334 | () => { 335 | pdf.start(); 336 | timeout.current = timeout.current * 2; 337 | forceRender(); 338 | }, 339 | ], 340 | ]} 341 | /> 342 | )} 343 | 344 | 345 | 346 | 360 | 374 | 375 |
376 |
377 | 378 | 379 | 380 | update({ isDebugging: !collapsed })} 384 | ref={debuggerAPI} 385 | > 386 | {state.isDebuggingSupported ? ( 387 | 391 | 392 | {layout && ( 393 | 394 | 395 | 396 | 397 | 398 | )} 399 | 400 | 401 | 402 | 403 | 404 | {selectedNode && selectedNode.style && ( 405 | 406 |
407 |                           {Object.entries(selectedNode.style)
408 |                             .map(([key, value]) => `${key}: ${value}`)
409 |                             .join("\n")}
410 |                         
411 |
412 | )} 413 | 414 | {selectedNode && ( 415 | 416 | 417 | 418 | )} 419 |
420 |
421 |
422 |
423 | ) : ( 424 | {`Debugger doesn't supported by this @react-pdf/renderer version`} 425 | )} 426 |
427 |
428 |
429 | ); 430 | 431 | return ( 432 | 433 | {isMobile ? ( 434 | 439 | {viewerPanel} 440 | 441 | {editorPanel} 442 | 443 | ) : ( 444 | 449 | {editorPanel} 450 | 451 | {viewerPanel} 452 | 453 | )} 454 | 455 | ); 456 | }; 457 | 458 | export default Repl; 459 | -------------------------------------------------------------------------------- /app/robots.js: -------------------------------------------------------------------------------- 1 | export default function robots() { 2 | return { 3 | rules: [ 4 | { 5 | userAgent: "*", 6 | }, 7 | ], 8 | sitemap: "https://react-pdf-repl.vercel.app/sitemap.xml", 9 | host: "https://react-pdf-repl.vercel.app", 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /app/sandpack/example/Document.jsx: -------------------------------------------------------------------------------- 1 | import { Text, Page, View, Document, Font } from "@react-pdf/renderer"; 2 | 3 | Font.registerEmojiSource({ 4 | format: "png", 5 | url: "https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/72x72/", 6 | }); 7 | 8 | export default function Example() { 9 | return ( 10 | 11 | 12 | 19 | 🚨 💅 💞 react-pdf and sandpack 🚨 💅 💓 20 | 21 | 22 | 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /app/sandpack/example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vite App 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/sandpack/example/index.jsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | import { PDFViewer } from "@react-pdf/renderer"; 4 | 5 | import MyDocument from "./Document"; 6 | import "./styles.css"; 7 | 8 | const root = createRoot(document.getElementById("root")); 9 | root.render( 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /app/sandpack/example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "dev": "vite", 4 | "build": "vite build", 5 | "preview": "vite preview" 6 | }, 7 | "dependencies": { 8 | "@react-pdf/renderer": "^3.1.9", 9 | "react": "^18.2.0", 10 | "react-dom": "^18.2.0" 11 | }, 12 | "devDependencies": { 13 | "@vitejs/plugin-react": "^4.0.0", 14 | "vite": "4.2.0", 15 | "esbuild-wasm": "^0.17.18" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/sandpack/example/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | } 4 | 5 | html, 6 | body, 7 | div#root, 8 | .Viewer { 9 | width: 100%; 10 | height: 100%; 11 | } 12 | 13 | .Viewer { 14 | display: block; 15 | border: none; 16 | } 17 | -------------------------------------------------------------------------------- /app/sandpack/example/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | 4 | export default defineConfig({ 5 | plugins: [react()], 6 | }); 7 | -------------------------------------------------------------------------------- /app/sandpack/global-styles.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { getSandpackCssText } from "@codesandbox/sandpack-react"; 4 | import { useServerInsertedHTML } from "next/navigation"; 5 | 6 | export const GlobalSandpackStyles = ({ children }) => { 7 | useServerInsertedHTML(() => { 8 | return ( 9 |