Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ node_modules
dist/
.tmp/
tmp/
.DS_Store
8 changes: 7 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"editor.formatOnSaveMode": "file",
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
Expand Down
2 changes: 1 addition & 1 deletion biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.6/schema.json",
"$schema": "https://biomejs.dev/schemas/2.4.7/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
Expand Down
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@
"README.md"
],
"scripts": {
"build": "biome check && tsup src/cli.tsx --format esm --clean && cp -r src/humans dist/ && npm run build:pdfs",
"build:ci": "biome check && tsup src/cli.tsx --format esm --clean && cp -r src/humans dist/",
"build": "biome check && tsup src/cli.tsx --format esm --clean && npm run copy:humans && npm run copy:pdfs && npm run build:pdfs",
"build:ci": "biome check && tsup src/cli.tsx --format esm --clean && npm run copy:humans",
"build:pdfs": "tsx scripts/pdf-gen/generate.ts --all",
"predev": "npm run build:pdfs",
"predev": "npm run build:pdfs && npm run copy:pdfs",
"dev": "tsx src/cli.tsx",
"test": "vitest run",
"format": "biome format --write",
"lint": "biome lint",
"lint:fix": "biome lint --write",
"biome:all": "biome format --write && biome lint --write",
"gen-pdf": "tsx scripts/pdf-gen/generate.ts",
"gen-json": "tsx scripts/json-gen/generate.ts",
"gen:pdf": "tsx scripts/pdf-gen/generate.ts",
"copy:pdfs": "tsx scripts/copy-pdfs/copy-pdfs.ts",
"copy:humans": "cp -r src/humans dist/",
"gen:json": "tsx scripts/json-gen/generate.ts",
"prepublishOnly": "npm run build"
},
"keywords": [],
Expand Down
Binary file added public/craig-cv.pdf
Binary file not shown.
1 change: 1 addition & 0 deletions scripts/copy-pdfs/__tests__/copy-pdfs-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "../_tests_/copy-pdfs.test";
76 changes: 76 additions & 0 deletions scripts/copy-pdfs/_tests_/copy-pdfs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";

import { copyStaticPdfs } from "../copy-pdfs";

function makeTempDir() {
return fs.mkdtempSync(path.join(os.tmpdir(), "run-cv-copy-pdfs-"));
}

describe("copyStaticPdfs", () => {
let tempRoot: string;

beforeEach(() => {
tempRoot = makeTempDir();
});

afterEach(() => {
fs.rmSync(tempRoot, { recursive: true, force: true });
});

it("copies PDF files from public into dist/pdf", () => {
const publicDir = path.join(tempRoot, "public");
const distPdfDir = path.join(tempRoot, "dist", "pdf");
const writes: string[] = [];

fs.mkdirSync(publicDir, { recursive: true });
fs.writeFileSync(path.join(publicDir, "craig-cv.pdf"), "CRAIG PDF");
fs.writeFileSync(path.join(publicDir, "baldur-cv.pdf"), "BALDUR PDF");
fs.writeFileSync(path.join(publicDir, "notes.txt"), "ignore me");

const result = copyStaticPdfs({
publicDir,
distPdfDir,
stdout: {
write(chunk: string) {
writes.push(chunk);
return true;
},
},
});

expect(result.copiedFiles).toEqual(["baldur-cv.pdf", "craig-cv.pdf"]);
expect(fs.readFileSync(path.join(distPdfDir, "craig-cv.pdf"), "utf8")).toBe(
"CRAIG PDF",
);
expect(
fs.readFileSync(path.join(distPdfDir, "baldur-cv.pdf"), "utf8"),
).toBe("BALDUR PDF");
expect(fs.existsSync(path.join(distPdfDir, "notes.txt"))).toBe(false);
expect(writes).toEqual([
`Copied 2 static PDF file(s) to ${path.resolve(distPdfDir)}\n`,
]);
});

it("throws when the public directory is missing", () => {
const publicDir = path.join(tempRoot, "missing-public");
const distPdfDir = path.join(tempRoot, "dist", "pdf");

expect(() => copyStaticPdfs({ publicDir, distPdfDir })).toThrow(
`Public directory not found: ${path.resolve(publicDir)}`,
);
});

it("throws when the public directory has no PDF files", () => {
const publicDir = path.join(tempRoot, "public");
const distPdfDir = path.join(tempRoot, "dist", "pdf");

fs.mkdirSync(publicDir, { recursive: true });
fs.writeFileSync(path.join(publicDir, "notes.txt"), "ignore me");

expect(() => copyStaticPdfs({ publicDir, distPdfDir })).toThrow(
`No PDF files found in ${path.resolve(publicDir)}`,
);
});
});
75 changes: 75 additions & 0 deletions scripts/copy-pdfs/copy-pdfs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

interface CopyStaticPdfsOptions {
publicDir: string;
distPdfDir: string;
stdout?: Pick<NodeJS.WriteStream, "write">;
}

interface CopyStaticPdfsResult {
copiedFiles: string[];
distPdfDir: string;
}

export function getCopyPdfPaths() {
const __dirname = path.dirname(fileURLToPath(import.meta.url));
return {
publicDir: path.resolve(__dirname, "../../public"),
distPdfDir: path.resolve(__dirname, "../../dist/pdf"),
};
}

export function copyStaticPdfs({
publicDir,
distPdfDir,
stdout = process.stdout,
}: CopyStaticPdfsOptions): CopyStaticPdfsResult {
const resolvedPublicDir = path.resolve(publicDir);
const resolvedDistPdfDir = path.resolve(distPdfDir);

if (!fs.existsSync(resolvedPublicDir)) {
throw new Error(`Public directory not found: ${resolvedPublicDir}`);
}

fs.mkdirSync(resolvedDistPdfDir, { recursive: true });

const files = fs
.readdirSync(resolvedPublicDir, { withFileTypes: true })
.filter((entry) => entry.isFile())
.map((entry) => entry.name)
.filter((name) => name.toLowerCase().endsWith(".pdf"));

if (files.length === 0) {
throw new Error(`No PDF files found in ${resolvedPublicDir}`);
}

for (const file of files) {
const source = path.join(resolvedPublicDir, file);
const target = path.join(resolvedDistPdfDir, file);
fs.copyFileSync(source, target);
}

stdout.write(
`Copied ${files.length} static PDF file(s) to ${resolvedDistPdfDir}\n`,
);

return {
copiedFiles: files,
distPdfDir: resolvedDistPdfDir,
};
}

function main() {
const { publicDir, distPdfDir } = getCopyPdfPaths();
copyStaticPdfs({ publicDir, distPdfDir });
}

function isDirectExecution() {
return process.argv[1] === fileURLToPath(import.meta.url);
}

if (isDirectExecution()) {
main();
}
Loading
Loading