mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-10-03 10:13:47 +10:00
The web preview, downloads, template gallery, server export and public PDF render through Forme. react-pdf, react-pdf-html, the react-pdf hyphenation package, the Phosphor react-pdf icons and the four patches are gone. Hyphenation now follows the page language for every language Forme has patterns for. Semantic CSS keeps its language; declarations Forme can't draw raise an ENGINE_UNSUPPORTED warning in the editor. The page map rebuilds blocks Forme leaves out of its layout when they break across pages, and a render that misplaces a box is repeated with nested rows kept whole. Tests move to a small shim with the react-pdf calls they were written against; tests of react-pdf internals are dropped. Forme limits are recorded as expected failures (RTL line order, characters above U+FFFF).
86 lines
2.6 KiB
TypeScript
86 lines
2.6 KiB
TypeScript
import type { TsdownPlugin } from "tsdown";
|
|
import { readdirSync, readFileSync } from "node:fs";
|
|
import { dirname, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { defineConfig } from "tsdown";
|
|
|
|
const rootPackageJson = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf-8")) as {
|
|
version?: string;
|
|
};
|
|
|
|
// Lambda disables require(ESM) and uses stricter CJS export detection than standalone Node.
|
|
const bundledInteropPackages = new Set([
|
|
"@uiw/color-convert",
|
|
"@babel/runtime",
|
|
"sanitize-html",
|
|
"htmlparser2",
|
|
"domhandler",
|
|
"domutils",
|
|
"domelementtype",
|
|
"dom-serializer",
|
|
"entities",
|
|
"deepmerge",
|
|
"escape-string-regexp",
|
|
"is-plain-object",
|
|
"parse-srcset",
|
|
"postcss",
|
|
"nanoid",
|
|
"picocolors",
|
|
"source-map-js",
|
|
"launder",
|
|
"dayjs",
|
|
]);
|
|
|
|
const shouldExternalizeThirdParty = (id: string) => {
|
|
const packageName = id
|
|
.split("/")
|
|
.slice(0, id.startsWith("@") ? 2 : 1)
|
|
.join("/");
|
|
if (id.startsWith("@reactive-resume/") || bundledInteropPackages.has(packageName)) return false;
|
|
// Subpath imports (`#…`) are resolved by the workspace package that declares them, so they're bundled with it.
|
|
if (id.startsWith("@/") || id.startsWith("#") || id.startsWith(".") || id.startsWith("/") || id.startsWith("\0"))
|
|
return false;
|
|
|
|
return true;
|
|
};
|
|
|
|
const aiPromptsDir = resolve(dirname(fileURLToPath(import.meta.url)), "../../packages/ai/src/prompts");
|
|
|
|
const promptAssetsPlugin: TsdownPlugin = {
|
|
name: "prompt-assets",
|
|
buildStart() {
|
|
for (const filename of readdirSync(aiPromptsDir)) {
|
|
if (!filename.endsWith(".md")) continue;
|
|
|
|
this.emitFile({
|
|
type: "asset",
|
|
fileName: `prompts/${filename}`,
|
|
source: readFileSync(resolve(aiPromptsDir, filename), "utf-8"),
|
|
});
|
|
}
|
|
},
|
|
};
|
|
|
|
export default defineConfig({
|
|
entry: { index: "src/index.ts", vercel: "src/vercel.ts", "prepare-deployment": "src/prepare-deployment.ts" },
|
|
// Keep import.meta.url-based asset lookup adjacent to the entrypoints.
|
|
outputOptions: { chunkFileNames: "[name]-[hash].mjs" },
|
|
format: "esm",
|
|
platform: "node",
|
|
target: "node24",
|
|
outDir: "dist",
|
|
clean: true,
|
|
shims: true,
|
|
dts: false,
|
|
define: { __APP_VERSION__: JSON.stringify(rootPackageJson.version ?? "0.0.0") },
|
|
// The flagged dynamic imports are deliberate: they defer evaluation of env-dependent
|
|
// modules so tests can run without env vars, not to split chunks.
|
|
suppressWarnings: [/dynamic import will not move module into another chunk/],
|
|
outExtensions: () => ({ js: ".mjs" }),
|
|
deps: {
|
|
alwaysBundle: [/^@reactive-resume\//, ...bundledInteropPackages],
|
|
neverBundle: shouldExternalizeThirdParty,
|
|
},
|
|
plugins: [promptAssetsPlugin],
|
|
});
|