diff --git a/backend/src/Infrastructure/MathComps.Infrastructure/Storage/IFileUploader.cs b/backend/src/Infrastructure/MathComps.Infrastructure/Storage/IFileUploader.cs index ba795f3..769e3b7 100644 --- a/backend/src/Infrastructure/MathComps.Infrastructure/Storage/IFileUploader.cs +++ b/backend/src/Infrastructure/MathComps.Infrastructure/Storage/IFileUploader.cs @@ -9,7 +9,7 @@ public interface IFileUploader /// Uploads a local file to remote storage at the specified key. /// /// Absolute path to the local file to upload. - /// The storage key (e.g., "handouts/factorization/factorization.sk.pdf"). + /// The storage key (e.g., "handouts/pdfs/factorization.sk.pdf"). /// A task representing the asynchronous upload operation. Task UploadAsync(string localFilePath, string key); } diff --git a/backend/src/Tools/MathComps.Cli.Handouts/BuildCommand.cs b/backend/src/Tools/MathComps.Cli.Handouts/BuildCommand.cs index 061596d..a0ade85 100644 --- a/backend/src/Tools/MathComps.Cli.Handouts/BuildCommand.cs +++ b/backend/src/Tools/MathComps.Cli.Handouts/BuildCommand.cs @@ -451,8 +451,8 @@ private static void CompileTexFile( } /// - /// Uploads a compiled handout PDF (main or skeleton) to remote storage, nesting it - /// under the handout's slug folder so every artefact for one handout sits together. + /// Uploads a compiled handout PDF (main or skeleton) to remote storage under + /// the flat handouts/pdfs/ folder shared by every handout. /// /// The .tex file whose corresponding PDF should be uploaded. /// The directory containing the compiled PDFs. @@ -471,8 +471,8 @@ private static async Task UploadHandoutPdfAsync(FileInfo texFile, DirectoryInfo return; } - // Build the R2 key so every artefact for one handout lands in the same folder - var r2Key = ToHandoutR2Key($"{ToHandoutSlug(texFile.Name)}/{pdfFileName}"); + // All handout PDFs share the flat handouts/pdfs/ folder + var r2Key = ToHandoutR2Key($"pdfs/{pdfFileName}"); await fileUploader.UploadAsync(sourcePdfPath, r2Key); AnsiConsole.MarkupLine($" [green]✓ PDF uploaded:[/] {Markup.Escape(pdfFileName)}"); } diff --git a/backend/src/Tools/MathComps.Cli.Handouts/README.md b/backend/src/Tools/MathComps.Cli.Handouts/README.md index 5703775..bbf9b01 100644 --- a/backend/src/Tools/MathComps.Cli.Handouts/README.md +++ b/backend/src/Tools/MathComps.Cli.Handouts/README.md @@ -10,7 +10,7 @@ For each matched `.tex` file, the tool runs these steps in order: 2. **Compile TeX** — runs the configured compiler (2 passes) on both main + skeleton files 3. **Parse to JSON** — converts the TeX document structure into `RawContentBlock[]` JSON (saved locally to `web/src/content/handouts/`) 4. **Upload images** — processes SVG images and uploads them to R2 under `handouts//.svg`, where `` is the language-stripped handout id (so all language variants share one image set) -5. **Upload PDFs** — uploads compiled main + skeleton PDFs to R2 under `handouts//.pdf` (same folder as the images) +5. **Upload PDFs** — uploads compiled main + skeleton PDFs to R2 under `handouts/pdfs/.pdf` (flat layout; every handout's PDFs share one folder) ## Prerequisites diff --git a/web/src/components/features/problems/services/problem-api-urls.ts b/web/src/components/features/problems/services/problem-api-urls.ts index 9211952..eed0096 100644 --- a/web/src/components/features/problems/services/problem-api-urls.ts +++ b/web/src/components/features/problems/services/problem-api-urls.ts @@ -24,17 +24,14 @@ export function getProblemImageUrl(contentId: string, type: ImageType): string { } /** - * Builds a public URL to a handout PDF by its filename. The handout's - * language-stripped slug is derived from the filename — both `..pdf` - * and `.-skeleton.pdf` collapse to the same slug so every artefact - * lives in one folder on R2. + * Builds a public URL to a handout PDF by its filename. All handout PDFs live + * together in the flat `handouts/pdfs/` folder on R2. * * @param filename - The PDF filename (e.g., "factorization.sk.pdf") * @returns The public URL to the PDF on R2 */ export function getHandoutPdfUrl(filename: string): string { - const slug = filename.replace(/\.[a-z]{2}(-skeleton)?\.pdf$/i, '') - return `${getR2BaseUrl()}/handouts/${slug}/${filename}` + return `${getR2BaseUrl()}/handouts/pdfs/${filename}` } /**