@ahmedrowaihi/pdf-forge-preview 1.0.0-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -0
- package/.next/app-path-routes-manifest.json +7 -0
- package/.next/build/chunks/[root-of-the-server]__12fb5caf._.js +233 -0
- package/.next/build/chunks/[root-of-the-server]__12fb5caf._.js.map +8 -0
- package/.next/build/chunks/[root-of-the-server]__242deb00._.js +500 -0
- package/.next/build/chunks/[root-of-the-server]__242deb00._.js.map +11 -0
- package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_ad9a1eec._.js +13 -0
- package/.next/build/chunks/[turbopack-node]_transforms_postcss_ts_ad9a1eec._.js.map +5 -0
- package/.next/build/chunks/[turbopack]_runtime.js +795 -0
- package/.next/build/chunks/[turbopack]_runtime.js.map +10 -0
- package/.next/build/chunks/node_modules__pnpm_806d01c0._.js +6758 -0
- package/.next/build/chunks/node_modules__pnpm_806d01c0._.js.map +47 -0
- package/.next/build/package.json +1 -0
- package/.next/build/postcss.js +6 -0
- package/.next/build/postcss.js.map +5 -0
- package/.next/build-manifest.json +20 -0
- package/.next/diagnostics/build-diagnostics.json +6 -0
- package/.next/diagnostics/framework.json +1 -0
- package/.next/export-marker.json +6 -0
- package/.next/fallback-build-manifest.json +12 -0
- package/.next/images-manifest.json +66 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +65 -0
- package/.next/required-server-files.js +163 -0
- package/.next/required-server-files.json +163 -0
- package/.next/routes-manifest.json +77 -0
- package/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_global-error/page/build-manifest.json +17 -0
- package/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
- package/.next/server/app/_global-error/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_global-error/page.js +11 -0
- package/.next/server/app/_global-error/page.js.map +5 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +2 -0
- package/.next/server/app/_global-error.html +2 -0
- package/.next/server/app/_global-error.meta +15 -0
- package/.next/server/app/_global-error.rsc +13 -0
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +5 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +13 -0
- package/.next/server/app/_global-error.segments/_head.segment.rsc +6 -0
- package/.next/server/app/_global-error.segments/_index.segment.rsc +4 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_not-found/page/build-manifest.json +17 -0
- package/.next/server/app/_not-found/page/next-font-manifest.json +16 -0
- package/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_not-found/page/server-reference-manifest.json +20 -0
- package/.next/server/app/_not-found/page.js +14 -0
- package/.next/server/app/_not-found/page.js.map +5 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +2 -0
- package/.next/server/app/favicon.ico/route/app-paths-manifest.json +3 -0
- package/.next/server/app/favicon.ico/route/build-manifest.json +11 -0
- package/.next/server/app/favicon.ico/route.js +6 -0
- package/.next/server/app/favicon.ico/route.js.map +5 -0
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/favicon.ico.meta +1 -0
- package/.next/server/app/page/app-paths-manifest.json +3 -0
- package/.next/server/app/page/build-manifest.json +17 -0
- package/.next/server/app/page/next-font-manifest.json +16 -0
- package/.next/server/app/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/page/server-reference-manifest.json +20 -0
- package/.next/server/app/page.js +17 -0
- package/.next/server/app/page.js.map +5 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +2 -0
- package/.next/server/app/preview/[...slug]/page/app-paths-manifest.json +3 -0
- package/.next/server/app/preview/[...slug]/page/build-manifest.json +17 -0
- package/.next/server/app/preview/[...slug]/page/next-font-manifest.json +16 -0
- package/.next/server/app/preview/[...slug]/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/preview/[...slug]/page/server-reference-manifest.json +65 -0
- package/.next/server/app/preview/[...slug]/page.js +19 -0
- package/.next/server/app/preview/[...slug]/page.js.map +5 -0
- package/.next/server/app/preview/[...slug]/page.js.nft.json +1 -0
- package/.next/server/app/preview/[...slug]/page_client-reference-manifest.js +2 -0
- package/.next/server/app-paths-manifest.json +7 -0
- package/.next/server/chunks/730ea_preview-server__next-internal_server_app_favicon_ico_route_actions_a71a8ae7.js +3 -0
- package/.next/server/chunks/730ea_preview-server__next-internal_server_app_favicon_ico_route_actions_a71a8ae7.js.map +1 -0
- package/.next/server/chunks/[externals]_next_dist_a6d89067._.js +3 -0
- package/.next/server/chunks/[externals]_next_dist_a6d89067._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__a62cd78d._.js +21 -0
- package/.next/server/chunks/[root-of-the-server]__a62cd78d._.js.map +1 -0
- package/.next/server/chunks/[turbopack]_runtime.js +795 -0
- package/.next/server/chunks/[turbopack]_runtime.js.map +10 -0
- package/.next/server/chunks/ssr/730ea_preview-server__next-internal_server_app__global-error_page_actions_986e2de5.js +3 -0
- package/.next/server/chunks/ssr/730ea_preview-server__next-internal_server_app__global-error_page_actions_986e2de5.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__025eaae9._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__025eaae9._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1536282c._.js +4 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1536282c._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__15cf9d36._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__15cf9d36._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__450f653e._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__450f653e._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__4874d0d7._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__4874d0d7._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__49771cdc._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__49771cdc._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__9ff74047._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__9ff74047._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__a9be37b1._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__a9be37b1._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__aeefe74e._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__aeefe74e._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__b13738d2._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__b13738d2._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__bb428c83._.js +4 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__bb428c83._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__c61333e3._.js +10 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__c61333e3._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__cb0c7b1a._.js +4 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__cb0c7b1a._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__dafcae4c._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__dafcae4c._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__e47d0c07._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__e47d0c07._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__ecac8617._.js +31 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__ecac8617._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__fd4bda25._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__fd4bda25._.js.map +1 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js +795 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js.map +10 -0
- package/.next/server/chunks/ssr/_19494208._.js +19 -0
- package/.next/server/chunks/ssr/_19494208._.js.map +1 -0
- package/.next/server/chunks/ssr/_810f54e9._.js +4 -0
- package/.next/server/chunks/ssr/_810f54e9._.js.map +1 -0
- package/.next/server/chunks/ssr/_aa01e67e._.js +4 -0
- package/.next/server/chunks/ssr/_aa01e67e._.js.map +1 -0
- package/.next/server/chunks/ssr/_bf10718b._.js +4 -0
- package/.next/server/chunks/ssr/_bf10718b._.js.map +1 -0
- package/.next/server/chunks/ssr/_c57c12df._.js +4 -0
- package/.next/server/chunks/ssr/_c57c12df._.js.map +1 -0
- package/.next/server/chunks/ssr/_d9b57cb8._.js +5 -0
- package/.next/server/chunks/ssr/_d9b57cb8._.js.map +1 -0
- package/.next/server/chunks/ssr/_e2a766a8._.js +3 -0
- package/.next/server/chunks/ssr/_e2a766a8._.js.map +1 -0
- package/.next/server/chunks/ssr/_e2b86512._.js +8 -0
- package/.next/server/chunks/ssr/_e2b86512._.js.map +1 -0
- package/.next/server/chunks/ssr/_ee8ea3aa._.js +19 -0
- package/.next/server/chunks/ssr/_ee8ea3aa._.js.map +1 -0
- package/.next/server/chunks/ssr/e8449_next_dist_5870db32._.js +3 -0
- package/.next/server/chunks/ssr/e8449_next_dist_5870db32._.js.map +1 -0
- package/.next/server/chunks/ssr/e8449_next_dist_client_components_builtin_forbidden_5542069c.js +3 -0
- package/.next/server/chunks/ssr/e8449_next_dist_client_components_builtin_forbidden_5542069c.js.map +1 -0
- package/.next/server/chunks/ssr/e8449_next_dist_client_components_builtin_global-error_d0870f3a.js +3 -0
- package/.next/server/chunks/ssr/e8449_next_dist_client_components_builtin_global-error_d0870f3a.js.map +1 -0
- package/.next/server/chunks/ssr/e8449_next_dist_client_components_builtin_unauthorized_4c01c8d5.js +3 -0
- package/.next/server/chunks/ssr/e8449_next_dist_client_components_builtin_unauthorized_4c01c8d5.js.map +1 -0
- package/.next/server/chunks/ssr/e8449_next_dist_client_components_d90ace34._.js +3 -0
- package/.next/server/chunks/ssr/e8449_next_dist_client_components_d90ace34._.js.map +1 -0
- package/.next/server/chunks/ssr/e8449_next_dist_esm_af7aafb8._.js +6 -0
- package/.next/server/chunks/ssr/e8449_next_dist_esm_af7aafb8._.js.map +1 -0
- package/.next/server/chunks/ssr/e8449_next_dist_esm_build_templates_app-page_f16f0848.js +4 -0
- package/.next/server/chunks/ssr/e8449_next_dist_esm_build_templates_app-page_f16f0848.js.map +1 -0
- package/.next/server/chunks/ssr/e8449_next_dist_f0d8a2cc._.js +4 -0
- package/.next/server/chunks/ssr/e8449_next_dist_f0d8a2cc._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules__pnpm_37510d96._.js +5 -0
- package/.next/server/chunks/ssr/node_modules__pnpm_37510d96._.js.map +1 -0
- package/.next/server/chunks/ssr/packages_preview-server_src_app_897ecf1c._.js +3 -0
- package/.next/server/chunks/ssr/packages_preview-server_src_app_897ecf1c._.js.map +1 -0
- package/.next/server/chunks/ssr/packages_preview-server_src_e17a2a9b._.js +3 -0
- package/.next/server/chunks/ssr/packages_preview-server_src_e17a2a9b._.js.map +1 -0
- package/.next/server/functions-config-manifest.json +4 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +21 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +34 -0
- package/.next/server/pages/500.html +2 -0
- package/.next/server/pages-manifest.json +3 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +80 -0
- package/.next/static/cdYIhKFtJ0GB-yJK5ywz_/_buildManifest.js +11 -0
- package/.next/static/cdYIhKFtJ0GB-yJK5ywz_/_clientMiddlewareManifest.json +1 -0
- package/.next/static/cdYIhKFtJ0GB-yJK5ywz_/_ssgManifest.js +1 -0
- package/.next/static/chunks/0464c7ff175ee6ff.js +1 -0
- package/.next/static/chunks/10468413db24762a.js +14 -0
- package/.next/static/chunks/2de338262e51ef94.js +3 -0
- package/.next/static/chunks/37adc260f85da877.js +1 -0
- package/.next/static/chunks/521eee9903bc4d1f.js +5 -0
- package/.next/static/chunks/6051bd38272cb442.js +14 -0
- package/.next/static/chunks/8d433d4b9d701456.js +1 -0
- package/.next/static/chunks/92ba72595aad9df6.js +1 -0
- package/.next/static/chunks/959ed978a6e89a66.js +1 -0
- package/.next/static/chunks/a6dad97d9634a72d.js +1 -0
- package/.next/static/chunks/a6dad97d9634a72d.js.map +1 -0
- package/.next/static/chunks/a6db6456c5b75734.js +1 -0
- package/.next/static/chunks/c3ece0a7e3e07076.js +1 -0
- package/.next/static/chunks/d1b29a74f6814a03.css +3 -0
- package/.next/static/chunks/f7ec22614fe1c1fe.js +1 -0
- package/.next/static/chunks/turbopack-e062a8e6d6034eb0.js +4 -0
- package/.next/static/media/1bffadaabf893a1e-s.7cd81963.woff2 +0 -0
- package/.next/static/media/2bbe8d2671613f1f-s.76dcb0b2.woff2 +0 -0
- package/.next/static/media/2c55a0e60120577a-s.2a48534a.woff2 +0 -0
- package/.next/static/media/5476f68d60460930-s.c995e352.woff2 +0 -0
- package/.next/static/media/83afe278b6a6bb3c-s.p.3a6ba036.woff2 +0 -0
- package/.next/static/media/9c72aa0f40e4eef8-s.18a48cbc.woff2 +0 -0
- package/.next/static/media/SFMonoBold-s.p.b90ec775.otf +0 -0
- package/.next/static/media/SFMonoHeavy-s.p.545fe93b.otf +0 -0
- package/.next/static/media/SFMonoLight-s.p.7c5363a6.otf +0 -0
- package/.next/static/media/SFMonoMedium-s.p.a4fc9904.otf +0 -0
- package/.next/static/media/SFMonoRegular-s.p.04ea7bf3.otf +0 -0
- package/.next/static/media/SFMonoSemibold-s.p.2d2ddb43.otf +0 -0
- package/.next/static/media/ad66f9afd8947f86-s.7a40eb73.woff2 +0 -0
- package/.next/static/media/favicon.678eb597.ico +0 -0
- package/.next/static/media/logo.22a370b0.png +0 -0
- package/.next/trace +1 -0
- package/.next/trace-build +1 -0
- package/.next/turbopack +0 -0
- package/.next/types/routes.d.ts +58 -0
- package/.next/types/validator.ts +70 -0
- package/CHANGELOG.md +12 -0
- package/LICENSE.md +8 -0
- package/index.mjs +17 -0
- package/jsx-runtime/jsx-dev-runtime.js +26 -0
- package/module-punycode.d.ts +3 -0
- package/next-env.d.ts +6 -0
- package/next.config.mjs +15 -0
- package/package.json +78 -0
- package/postcss.config.js +5 -0
- package/readme.md +33 -0
- package/scripts/build-preview-server.mts +25 -0
- package/scripts/dev.mts +57 -0
- package/scripts/seed.mts +36 -0
- package/src/actions/export-single-template.ts +74 -0
- package/src/actions/get-template-path-from-slug.ts +32 -0
- package/src/actions/get-templates-directory-metadata-action.ts +19 -0
- package/src/actions/render-template-by-path.tsx +313 -0
- package/src/actions/safe-action.ts +15 -0
- package/src/animated-icons-data/help.json +1082 -0
- package/src/animated-icons-data/link.json +1309 -0
- package/src/animated-icons-data/load.json +443 -0
- package/src/animated-icons-data/mail.json +1320 -0
- package/src/app/env.ts +14 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/fonts/SFMono/SFMonoBold.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoBoldItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoHeavy.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoHeavyItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoLight.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoLightItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoMedium.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoMediumItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoRegular.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoRegularItalic.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoSemibold.otf +0 -0
- package/src/app/fonts/SFMono/SFMonoSemiboldItalic.otf +0 -0
- package/src/app/fonts.ts +39 -0
- package/src/app/globals.css +136 -0
- package/src/app/layout.tsx +46 -0
- package/src/app/logo.png +0 -0
- package/src/app/page.tsx +52 -0
- package/src/app/preview/[...slug]/download-button.tsx +138 -0
- package/src/app/preview/[...slug]/error-overlay.tsx +58 -0
- package/src/app/preview/[...slug]/page.tsx +90 -0
- package/src/app/preview/[...slug]/preview.tsx +249 -0
- package/src/app/preview/[...slug]/template-frame.tsx +68 -0
- package/src/components/button.tsx +101 -0
- package/src/components/code-container.tsx +169 -0
- package/src/components/code-snippet.tsx +9 -0
- package/src/components/code.tsx +185 -0
- package/src/components/heading.tsx +113 -0
- package/src/components/icons/icon-arrow-down.tsx +16 -0
- package/src/components/icons/icon-base.tsx +26 -0
- package/src/components/icons/icon-bug.tsx +19 -0
- package/src/components/icons/icon-button.tsx +23 -0
- package/src/components/icons/icon-check.tsx +19 -0
- package/src/components/icons/icon-clipboard.tsx +40 -0
- package/src/components/icons/icon-cloud-alert.tsx +18 -0
- package/src/components/icons/icon-cloud-check.tsx +17 -0
- package/src/components/icons/icon-download.tsx +19 -0
- package/src/components/icons/icon-file.tsx +19 -0
- package/src/components/icons/icon-folder-open.tsx +19 -0
- package/src/components/icons/icon-folder.tsx +18 -0
- package/src/components/icons/icon-hide-sidebar.tsx +23 -0
- package/src/components/icons/icon-image.tsx +19 -0
- package/src/components/icons/icon-info.tsx +18 -0
- package/src/components/icons/icon-link.tsx +14 -0
- package/src/components/icons/icon-loader.tsx +16 -0
- package/src/components/icons/icon-monitor.tsx +19 -0
- package/src/components/icons/icon-moon.tsx +16 -0
- package/src/components/icons/icon-phone.tsx +26 -0
- package/src/components/icons/icon-reload.tsx +18 -0
- package/src/components/icons/icon-source.tsx +19 -0
- package/src/components/icons/icon-stamp.tsx +14 -0
- package/src/components/icons/icon-sun.tsx +74 -0
- package/src/components/icons/icon-warning.tsx +31 -0
- package/src/components/index.ts +7 -0
- package/src/components/logo.tsx +41 -0
- package/src/components/resizable-wrapper.tsx +269 -0
- package/src/components/shell.tsx +95 -0
- package/src/components/sidebar/file-tree-directory-children.tsx +142 -0
- package/src/components/sidebar/file-tree-directory.tsx +92 -0
- package/src/components/sidebar/file-tree.tsx +31 -0
- package/src/components/sidebar/index.ts +1 -0
- package/src/components/sidebar/sidebar.tsx +46 -0
- package/src/components/text.tsx +99 -0
- package/src/components/toolbar/checking-results.tsx +150 -0
- package/src/components/toolbar/code-preview-line-link.tsx +39 -0
- package/src/components/toolbar/results-table.tsx +0 -0
- package/src/components/toolbar/results.tsx +52 -0
- package/src/components/toolbar/toolbar-button.tsx +52 -0
- package/src/components/toolbar/use-cached-state.ts +36 -0
- package/src/components/toolbar.tsx +182 -0
- package/src/components/tooltip-content.tsx +31 -0
- package/src/components/tooltip.tsx +19 -0
- package/src/components/topbar/active-view-toggle-group.tsx +86 -0
- package/src/components/topbar/emulated-dark-mode-toggle.tsx +58 -0
- package/src/components/topbar/view-size-controls.tsx +173 -0
- package/src/components/topbar.tsx +59 -0
- package/src/contexts/preview.tsx +91 -0
- package/src/contexts/templates.tsx +57 -0
- package/src/contexts/toolbar.tsx +22 -0
- package/src/hooks/use-clamped-state.ts +24 -0
- package/src/hooks/use-fragment-identifier.ts +14 -0
- package/src/hooks/use-hot-reload.ts +31 -0
- package/src/hooks/use-rendering-metadata.ts +37 -0
- package/src/hooks/use-template-rendering-result.ts +58 -0
- package/src/utils/cn.ts +6 -0
- package/src/utils/constants.ts +8 -0
- package/src/utils/contains-template.ts +52 -0
- package/src/utils/convert-stack-with-sourcemap.ts +79 -0
- package/src/utils/copy-text-to-clipboard.ts +7 -0
- package/src/utils/create-jsx-runtime.ts +47 -0
- package/src/utils/esbuild/escape-string-for-regex.ts +3 -0
- package/src/utils/esbuild/renderring-utilities-exporter.ts +64 -0
- package/src/utils/get-line-and-column-from-offset.ts +11 -0
- package/src/utils/get-template-component.ts +158 -0
- package/src/utils/get-templates-directory-metadata.ts +195 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/language-map.ts +7 -0
- package/src/utils/load-stream.ts +15 -0
- package/src/utils/register-spinner-autostopping.ts +28 -0
- package/src/utils/result.ts +49 -0
- package/src/utils/run-bundled-code.ts +86 -0
- package/src/utils/sanitize.ts +6 -0
- package/src/utils/sleep.ts +3 -0
- package/src/utils/snake-to-camel.ts +5 -0
- package/src/utils/static-node-modules-for-vm.ts +93 -0
- package/src/utils/style-text.ts +11 -0
- package/src/utils/types/as.ts +26 -0
- package/src/utils/types/error-object.ts +11 -0
- package/src/utils/types/hot-reload-change.ts +13 -0
- package/src/utils/types/template.ts +8 -0
- package/src/utils/unreachable.ts +8 -0
- package/templates/.gitkeep +0 -0
- package/tsconfig.json +47 -0
package/src/app/env.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** ONLY ACCESSIBLE ON THE SERVER */
|
|
2
|
+
export const userProjectLocation = process.env.USER_PROJECT_LOCATION!;
|
|
3
|
+
|
|
4
|
+
/** ONLY ACCESSIBLE ON THE SERVER */
|
|
5
|
+
export const previewServerLocation = process.env.PREVIEW_SERVER_LOCATION!;
|
|
6
|
+
|
|
7
|
+
/** ONLY ACCESSIBLE ON THE SERVER */
|
|
8
|
+
export const templatesDirectoryAbsolutePath =
|
|
9
|
+
process.env.TEMPLATES_DIR_ABSOLUTE_PATH!;
|
|
10
|
+
|
|
11
|
+
export const isBuilding = process.env.NEXT_PUBLIC_IS_BUILDING === 'true';
|
|
12
|
+
|
|
13
|
+
export const isPreviewDevelopment =
|
|
14
|
+
process.env.NEXT_PUBLIC_IS_PREVIEW_DEVELOPMENT === 'true';
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/app/fonts.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Inter } from 'next/font/google';
|
|
2
|
+
import Local from 'next/font/local';
|
|
3
|
+
|
|
4
|
+
export const inter = Inter({
|
|
5
|
+
subsets: ['latin'],
|
|
6
|
+
variable: '--font-inter',
|
|
7
|
+
display: 'swap',
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const sfMono = Local({
|
|
11
|
+
src: [
|
|
12
|
+
{
|
|
13
|
+
path: './fonts/SFMono/SFMonoLight.otf',
|
|
14
|
+
weight: '300',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
path: './fonts/SFMono/SFMonoRegular.otf',
|
|
18
|
+
weight: '400',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
path: './fonts/SFMono/SFMonoMedium.otf',
|
|
22
|
+
weight: '500',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
path: './fonts/SFMono/SFMonoSemibold.otf',
|
|
26
|
+
weight: '600',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
path: './fonts/SFMono/SFMonoBold.otf',
|
|
30
|
+
weight: '700',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
path: './fonts/SFMono/SFMonoHeavy.otf',
|
|
34
|
+
weight: '800',
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
variable: '--font-sf-mono',
|
|
38
|
+
display: 'swap',
|
|
39
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
|
|
3
|
+
@theme {
|
|
4
|
+
--background-image-gradient: linear-gradient(
|
|
5
|
+
145.37deg,
|
|
6
|
+
rgba(255, 255, 255, 0.09) -8.75%,
|
|
7
|
+
rgba(255, 255, 255, 0.027) 83.95%
|
|
8
|
+
);
|
|
9
|
+
--background-image-gradient-hover: linear-gradient(
|
|
10
|
+
145.37deg,
|
|
11
|
+
rgba(255, 255, 255, 0.1) -8.75%,
|
|
12
|
+
rgba(255, 255, 255, 0.057) 83.95%
|
|
13
|
+
);
|
|
14
|
+
--background-image-shine: linear-gradient(
|
|
15
|
+
45deg,
|
|
16
|
+
rgba(255, 255, 255, 0) 45%,
|
|
17
|
+
rgba(255, 255, 255, 1) 50%,
|
|
18
|
+
rgba(255, 255, 255, 0) 55%,
|
|
19
|
+
rgba(255, 255, 255, 0) 100%
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
--color-cyan-1: #0091f70a;
|
|
23
|
+
--color-cyan-2: #02a7f211;
|
|
24
|
+
--color-cyan-3: #00befd28;
|
|
25
|
+
--color-cyan-4: #00baff3b;
|
|
26
|
+
--color-cyan-5: #00befd4d;
|
|
27
|
+
--color-cyan-6: #00c7fd5e;
|
|
28
|
+
--color-cyan-7: #14cdff75;
|
|
29
|
+
--color-cyan-8: #11cfff95;
|
|
30
|
+
--color-cyan-9: #00cfffc3;
|
|
31
|
+
--color-cyan-10: #28d6ffcd;
|
|
32
|
+
--color-cyan-11: #52e1fee5;
|
|
33
|
+
--color-cyan-12: #bbf3fef7;
|
|
34
|
+
|
|
35
|
+
--color-slate-1: #00000000;
|
|
36
|
+
--color-slate-2: #d8f4f609;
|
|
37
|
+
--color-slate-3: #ddeaf814;
|
|
38
|
+
--color-slate-4: #d3edf81d;
|
|
39
|
+
--color-slate-5: #d9edfe25;
|
|
40
|
+
--color-slate-6: #d6ebfd30;
|
|
41
|
+
--color-slate-7: #d9edff40;
|
|
42
|
+
--color-slate-8: #d9edff5d;
|
|
43
|
+
--color-slate-9: #dfebfd6d;
|
|
44
|
+
--color-slate-10: #e5edfd7b;
|
|
45
|
+
--color-slate-11: #f1f7feb5;
|
|
46
|
+
--color-slate-12: #fcfdffef;
|
|
47
|
+
|
|
48
|
+
--font-sans:
|
|
49
|
+
var(--font-inter), ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
|
|
50
|
+
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
51
|
+
--font-mono:
|
|
52
|
+
var(--font-sf-mono), ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
53
|
+
"Liberation Mono", "Courier New", monospace;
|
|
54
|
+
|
|
55
|
+
--animate-spin-slow: spin 3s linear infinite;
|
|
56
|
+
--animate-spin-fast: spin 1.5s linear infinite;
|
|
57
|
+
|
|
58
|
+
@keyframes shine {
|
|
59
|
+
0% {
|
|
60
|
+
background-position: -100%;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
100% {
|
|
64
|
+
background-position: 100%;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@keyframes dash {
|
|
69
|
+
0% {
|
|
70
|
+
stroke-dashoffset: 1000;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
100% {
|
|
74
|
+
stroke-dashoffset: 0;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@keyframes spin {
|
|
79
|
+
0% {
|
|
80
|
+
transform: rotate(0deg);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
100% {
|
|
84
|
+
transform: rotate(360deg);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@utility arrow-hide {
|
|
90
|
+
appearance: textfield;
|
|
91
|
+
|
|
92
|
+
&::-webkit-inner-spin-button {
|
|
93
|
+
appearance: none;
|
|
94
|
+
margin: 0px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
&::-webkit-outer-spin-button {
|
|
98
|
+
appearance: none;
|
|
99
|
+
margin: 0px;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/*
|
|
104
|
+
The default border color has changed to `currentcolor` in Tailwind CSS v4,
|
|
105
|
+
so we've added these compatibility styles to make sure everything still
|
|
106
|
+
looks the same as it did with Tailwind CSS v3.
|
|
107
|
+
|
|
108
|
+
If we ever want to remove these styles, we need to add an explicit border
|
|
109
|
+
color utility to any element that depends on these defaults.
|
|
110
|
+
*/
|
|
111
|
+
@layer base {
|
|
112
|
+
*,
|
|
113
|
+
::after,
|
|
114
|
+
::before,
|
|
115
|
+
::backdrop,
|
|
116
|
+
::file-selector-button {
|
|
117
|
+
border-color: var(--color-gray-200, currentcolor);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
button:not(:disabled),
|
|
121
|
+
[role="button"]:not(:disabled) {
|
|
122
|
+
cursor: pointer;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
html {
|
|
127
|
+
color-scheme: dark;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.popup-open iframe {
|
|
131
|
+
pointer-events: none;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
nav > div > div > .line {
|
|
135
|
+
display: none;
|
|
136
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import './globals.css';
|
|
2
|
+
|
|
3
|
+
import type { Metadata } from 'next';
|
|
4
|
+
import { TemplatesProvider } from '../contexts/templates';
|
|
5
|
+
import { getTemplatesDirectoryMetadata } from '../utils/get-templates-directory-metadata';
|
|
6
|
+
import { templatesDirectoryAbsolutePath } from './env';
|
|
7
|
+
import { inter, sfMono } from './fonts';
|
|
8
|
+
|
|
9
|
+
export const metadata: Metadata = {
|
|
10
|
+
title: 'React PDF Forge',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const dynamic = 'force-dynamic';
|
|
14
|
+
|
|
15
|
+
export default async function RootLayout({
|
|
16
|
+
children,
|
|
17
|
+
}: {
|
|
18
|
+
children: React.ReactNode;
|
|
19
|
+
}) {
|
|
20
|
+
const templatesDirectoryMetadata = await getTemplatesDirectoryMetadata(
|
|
21
|
+
templatesDirectoryAbsolutePath,
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
if (typeof templatesDirectoryMetadata === 'undefined') {
|
|
25
|
+
throw new Error(
|
|
26
|
+
`Could not find the templates directory specified under ${templatesDirectoryAbsolutePath}!`,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<html
|
|
32
|
+
className={`${inter.variable} ${sfMono.variable} font-sans`}
|
|
33
|
+
lang="en"
|
|
34
|
+
>
|
|
35
|
+
<body className="relative h-screen bg-black text-slate-11 leading-loose selection:bg-cyan-5 selection:text-cyan-12">
|
|
36
|
+
<div className="bg-linear-to-t from-slate-3 flex flex-col">
|
|
37
|
+
<TemplatesProvider
|
|
38
|
+
initialTemplatesDirectoryMetadata={templatesDirectoryMetadata}
|
|
39
|
+
>
|
|
40
|
+
{children}
|
|
41
|
+
</TemplatesProvider>
|
|
42
|
+
</div>
|
|
43
|
+
</body>
|
|
44
|
+
</html>
|
|
45
|
+
);
|
|
46
|
+
}
|
package/src/app/logo.png
ADDED
|
Binary file
|
package/src/app/page.tsx
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import Image from 'next/image';
|
|
3
|
+
import Link from 'next/link';
|
|
4
|
+
import { Button, Heading, Text } from '../components';
|
|
5
|
+
import CodeSnippet from '../components/code-snippet';
|
|
6
|
+
import { Shell } from '../components/shell';
|
|
7
|
+
import { templatesDirectoryAbsolutePath } from './env';
|
|
8
|
+
import logo from './logo.png';
|
|
9
|
+
|
|
10
|
+
export default function Home() {
|
|
11
|
+
const baseTemplatesDirectoryName = path.basename(
|
|
12
|
+
templatesDirectoryAbsolutePath,
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<Shell>
|
|
17
|
+
<div className="w-full h-full flex items-center justify-center p-8">
|
|
18
|
+
<div className="-mt-10 relative max-w-lg flex flex-col items-center gap-3 text-center">
|
|
19
|
+
<Image
|
|
20
|
+
alt="React PDF Forge Icon"
|
|
21
|
+
className="mb-8"
|
|
22
|
+
height={144}
|
|
23
|
+
src={logo}
|
|
24
|
+
style={{
|
|
25
|
+
borderRadius: 34,
|
|
26
|
+
boxShadow: '0 .625rem 12.5rem 1.25rem #2B7CA080',
|
|
27
|
+
}}
|
|
28
|
+
width={141}
|
|
29
|
+
/>
|
|
30
|
+
<Heading as="h2" size="6" weight="medium">
|
|
31
|
+
Welcome to React PDF Forge
|
|
32
|
+
</Heading>
|
|
33
|
+
<Text as="p">
|
|
34
|
+
To start developing your PDF templates, you can create a<br />
|
|
35
|
+
<CodeSnippet>.jsx</CodeSnippet> or <CodeSnippet>.tsx</CodeSnippet>{' '}
|
|
36
|
+
file under your{' '}
|
|
37
|
+
<CodeSnippet>{baseTemplatesDirectoryName}</CodeSnippet> folder.
|
|
38
|
+
</Text>
|
|
39
|
+
<Button asChild className="mt-3" size="3">
|
|
40
|
+
<Link
|
|
41
|
+
href="https://github.com/ahmedrowaihi/react-pdf-forge"
|
|
42
|
+
target="_blank"
|
|
43
|
+
rel="noopener noreferrer"
|
|
44
|
+
>
|
|
45
|
+
Check the docs
|
|
46
|
+
</Link>
|
|
47
|
+
</Button>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</Shell>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { toast } from 'sonner';
|
|
5
|
+
import { exportSingleTemplate } from '../../../actions/export-single-template';
|
|
6
|
+
import { IconFile } from '../../../components/icons/icon-file';
|
|
7
|
+
import { IconImage } from '../../../components/icons/icon-image';
|
|
8
|
+
import { Tooltip } from '../../../components/tooltip';
|
|
9
|
+
import { cn } from '../../../utils';
|
|
10
|
+
|
|
11
|
+
interface DownloadButtonProps {
|
|
12
|
+
templateSlug: string;
|
|
13
|
+
htmlMarkup: string;
|
|
14
|
+
darkMode?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type ExportFormat = 'pdf' | 'screenshot';
|
|
18
|
+
|
|
19
|
+
export const DownloadButton = ({
|
|
20
|
+
templateSlug,
|
|
21
|
+
htmlMarkup,
|
|
22
|
+
darkMode = false,
|
|
23
|
+
}: DownloadButtonProps) => {
|
|
24
|
+
const [isLoadingPdf, setIsLoadingPdf] = useState(false);
|
|
25
|
+
const [isLoadingScreenshot, setIsLoadingScreenshot] = useState(false);
|
|
26
|
+
|
|
27
|
+
const templateName = templateSlug.replace(/\.[^/.]+$/, '');
|
|
28
|
+
|
|
29
|
+
const handleOpen = async (format: ExportFormat) => {
|
|
30
|
+
if (format === 'pdf') {
|
|
31
|
+
setIsLoadingPdf(true);
|
|
32
|
+
} else {
|
|
33
|
+
setIsLoadingScreenshot(true);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const result = await exportSingleTemplate({
|
|
38
|
+
name: templateName,
|
|
39
|
+
html: htmlMarkup,
|
|
40
|
+
format,
|
|
41
|
+
darkMode,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (result?.serverError) {
|
|
45
|
+
toast.error(result.serverError);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!result?.data) {
|
|
50
|
+
toast.error('Failed to export template');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const resultData = result.data;
|
|
55
|
+
|
|
56
|
+
if (resultData.format === 'html' || !('data' in resultData)) {
|
|
57
|
+
toast.error('Invalid export format');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const resultFormat = resultData.format;
|
|
62
|
+
|
|
63
|
+
const binaryString = atob(resultData.data);
|
|
64
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
65
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
66
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
67
|
+
}
|
|
68
|
+
const blob = new Blob([bytes], { type: resultData.mimeType });
|
|
69
|
+
const url = URL.createObjectURL(blob);
|
|
70
|
+
window.open(url, '_blank');
|
|
71
|
+
setTimeout(() => URL.revokeObjectURL(url), 100);
|
|
72
|
+
toast.success(
|
|
73
|
+
`${resultFormat === 'pdf' ? 'PDF' : 'Screenshot'} opened in new window`,
|
|
74
|
+
);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error('Export error:', error);
|
|
77
|
+
toast.error(
|
|
78
|
+
error instanceof Error
|
|
79
|
+
? error.message
|
|
80
|
+
: 'Failed to export template. Make sure the PDF Forge server is running.',
|
|
81
|
+
);
|
|
82
|
+
} finally {
|
|
83
|
+
if (format === 'pdf') {
|
|
84
|
+
setIsLoadingPdf(false);
|
|
85
|
+
} else {
|
|
86
|
+
setIsLoadingScreenshot(false);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const isLoading = isLoadingPdf || isLoadingScreenshot;
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<div className="flex gap-2">
|
|
95
|
+
<Tooltip>
|
|
96
|
+
<Tooltip.Trigger asChild>
|
|
97
|
+
<button
|
|
98
|
+
disabled={isLoading}
|
|
99
|
+
type="button"
|
|
100
|
+
onClick={() => {
|
|
101
|
+
void handleOpen('pdf');
|
|
102
|
+
}}
|
|
103
|
+
className={cn(
|
|
104
|
+
'relative w-9 h-9 flex items-center justify-center border border-slate-6 text-sm rounded-lg transition duration-200 ease-in-out',
|
|
105
|
+
'text-slate-11 hover:text-slate-12',
|
|
106
|
+
'disabled:opacity-50 disabled:cursor-not-allowed',
|
|
107
|
+
isLoadingPdf && 'bg-slate-4',
|
|
108
|
+
)}
|
|
109
|
+
>
|
|
110
|
+
<IconFile size={16} />
|
|
111
|
+
</button>
|
|
112
|
+
</Tooltip.Trigger>
|
|
113
|
+
<Tooltip.Content>Open as PDF</Tooltip.Content>
|
|
114
|
+
</Tooltip>
|
|
115
|
+
|
|
116
|
+
<Tooltip>
|
|
117
|
+
<Tooltip.Trigger asChild>
|
|
118
|
+
<button
|
|
119
|
+
disabled={isLoading}
|
|
120
|
+
type="button"
|
|
121
|
+
onClick={() => {
|
|
122
|
+
void handleOpen('screenshot');
|
|
123
|
+
}}
|
|
124
|
+
className={cn(
|
|
125
|
+
'relative w-9 h-9 flex items-center justify-center border border-slate-6 text-sm rounded-lg transition duration-200 ease-in-out',
|
|
126
|
+
'text-slate-11 hover:text-slate-12',
|
|
127
|
+
'disabled:opacity-50 disabled:cursor-not-allowed',
|
|
128
|
+
isLoadingScreenshot && 'bg-slate-4',
|
|
129
|
+
)}
|
|
130
|
+
>
|
|
131
|
+
<IconImage size={16} />
|
|
132
|
+
</button>
|
|
133
|
+
</Tooltip.Trigger>
|
|
134
|
+
<Tooltip.Content>Open as Screenshot</Tooltip.Content>
|
|
135
|
+
</Tooltip>
|
|
136
|
+
</div>
|
|
137
|
+
);
|
|
138
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { ErrorObject } from '../../../utils/types/error-object';
|
|
4
|
+
|
|
5
|
+
interface ErrorOverlayProps {
|
|
6
|
+
error: ErrorObject;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const Message = ({ children: content }: { children: string }) => {
|
|
10
|
+
const match = content.match(
|
|
11
|
+
/(Unexpected closing tag "[^"]+". It may happen when the tag has already been closed by another tag). (For more info see) (.+)/,
|
|
12
|
+
);
|
|
13
|
+
if (match) {
|
|
14
|
+
const [_, errorMessage, moreInfo, link] = match;
|
|
15
|
+
return (
|
|
16
|
+
<>
|
|
17
|
+
{errorMessage}.
|
|
18
|
+
<p className="text-lg">
|
|
19
|
+
{moreInfo}{' '}
|
|
20
|
+
<a className="underline" rel="noreferrer" target="_blank" href={link}>
|
|
21
|
+
{link}
|
|
22
|
+
</a>
|
|
23
|
+
</p>
|
|
24
|
+
</>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return content;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const ErrorOverlay = ({ error }: ErrorOverlayProps) => {
|
|
31
|
+
return (
|
|
32
|
+
<>
|
|
33
|
+
<div className="absolute inset-0 z-50 bg-black/80" />
|
|
34
|
+
<div
|
|
35
|
+
className="
|
|
36
|
+
min-h-[50vh] w-full max-w-lg sm:rounded-lg md:max-w-[568px] lg:max-w-[920px]
|
|
37
|
+
absolute left-[50%] top-[50%] z-50 translate-x-[-50%] translate-y-[-50%]
|
|
38
|
+
rounded-t-sm overflow-hidden bg-white text-black shadow-lg duration-200
|
|
39
|
+
flex flex-col selection:text-black!
|
|
40
|
+
"
|
|
41
|
+
>
|
|
42
|
+
<div className="bg-red-500 h-3" />
|
|
43
|
+
<div className="flex grow p-6 min-w-0 max-w-full flex-col space-y-1.5">
|
|
44
|
+
<div className="shrink pb-2 text-xl tracking-tight">
|
|
45
|
+
<b>{error.name}</b>: <Message>{error.message}</Message>
|
|
46
|
+
</div>
|
|
47
|
+
{error.stack ? (
|
|
48
|
+
<div className="grow scroll-px-4 overflow-x-auto rounded-lg bg-black p-2 text-gray-100">
|
|
49
|
+
<pre className="w-full min-w-0 font-mono leading-6 selection:text-cyan-12! text-xs">
|
|
50
|
+
{error.stack}
|
|
51
|
+
</pre>
|
|
52
|
+
</div>
|
|
53
|
+
) : undefined}
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { redirect } from 'next/navigation';
|
|
3
|
+
import { Suspense } from 'react';
|
|
4
|
+
import { getTemplatePathFromSlug } from '../../../actions/get-template-path-from-slug';
|
|
5
|
+
import { renderTemplateByPath } from '../../../actions/render-template-by-path';
|
|
6
|
+
import { Shell } from '../../../components/shell';
|
|
7
|
+
import { Toolbar } from '../../../components/toolbar';
|
|
8
|
+
import { PreviewProvider } from '../../../contexts/preview';
|
|
9
|
+
import { getTemplatesDirectoryMetadata } from '../../../utils/get-templates-directory-metadata';
|
|
10
|
+
import { isBuilding, templatesDirectoryAbsolutePath } from '../../env';
|
|
11
|
+
import Preview from './preview';
|
|
12
|
+
|
|
13
|
+
export const dynamicParams = true;
|
|
14
|
+
|
|
15
|
+
export const dynamic = 'force-dynamic';
|
|
16
|
+
|
|
17
|
+
export interface PreviewParams {
|
|
18
|
+
slug: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default async function Page({
|
|
22
|
+
params: paramsPromise,
|
|
23
|
+
}: {
|
|
24
|
+
params: Promise<PreviewParams>;
|
|
25
|
+
}) {
|
|
26
|
+
const params = await paramsPromise;
|
|
27
|
+
// will come in here as segments of a relative path to the template
|
|
28
|
+
// ex: ['authentication', 'verify-password.tsx']
|
|
29
|
+
const slug = decodeURIComponent(params.slug.join('/'));
|
|
30
|
+
const templatesDirMetadata = await getTemplatesDirectoryMetadata(
|
|
31
|
+
templatesDirectoryAbsolutePath,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
if (typeof templatesDirMetadata === 'undefined') {
|
|
35
|
+
throw new Error(
|
|
36
|
+
`Could not find the templates directory specified under ${templatesDirectoryAbsolutePath}!
|
|
37
|
+
|
|
38
|
+
This is most likely not an issue with the preview server. Maybe there was a typo on the "--dir" flag?`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let templatePath: string;
|
|
43
|
+
try {
|
|
44
|
+
templatePath = await getTemplatePathFromSlug(slug);
|
|
45
|
+
} catch (exception) {
|
|
46
|
+
if (exception instanceof Error) {
|
|
47
|
+
console.warn(exception.message);
|
|
48
|
+
redirect('/');
|
|
49
|
+
}
|
|
50
|
+
throw exception;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const serverTemplateRenderingResult =
|
|
54
|
+
await renderTemplateByPath(templatePath);
|
|
55
|
+
|
|
56
|
+
if (isBuilding && 'error' in serverTemplateRenderingResult) {
|
|
57
|
+
throw new Error(serverTemplateRenderingResult.error.message, {
|
|
58
|
+
cause: serverTemplateRenderingResult.error,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<PreviewProvider
|
|
64
|
+
templateSlug={slug}
|
|
65
|
+
templatePath={templatePath}
|
|
66
|
+
serverRenderingResult={serverTemplateRenderingResult}
|
|
67
|
+
>
|
|
68
|
+
<Shell currentTemplateOpenSlug={slug}>
|
|
69
|
+
{/* This suspense is so that this page doesn't throw warnings */}
|
|
70
|
+
{/* on the build of the preview server de-opting into */}
|
|
71
|
+
{/* client-side rendering on build */}
|
|
72
|
+
<Suspense>
|
|
73
|
+
<Preview templateTitle={path.basename(templatePath)} />
|
|
74
|
+
|
|
75
|
+
<Toolbar />
|
|
76
|
+
</Suspense>
|
|
77
|
+
</Shell>
|
|
78
|
+
</PreviewProvider>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function generateMetadata({
|
|
83
|
+
params,
|
|
84
|
+
}: {
|
|
85
|
+
params: Promise<PreviewParams>;
|
|
86
|
+
}) {
|
|
87
|
+
const { slug } = await params;
|
|
88
|
+
|
|
89
|
+
return { title: `${path.basename(slug.join('/'))} — React PDF Forge` };
|
|
90
|
+
}
|