diff --git a/Public/css/output.css b/Public/css/output.css index 6ec6839..c1e23d1 100644 --- a/Public/css/output.css +++ b/Public/css/output.css @@ -8548,6 +8548,10 @@ .italic { font-style: italic; } + .lining-nums { + --tw-numeric-figure: lining-nums; + font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,); + } .tabular-nums { --tw-numeric-spacing: tabular-nums; font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,); diff --git a/Sources/App/Middleware/ViewRoute+middleware.swift b/Sources/App/Middleware/ViewRoute+middleware.swift index c3cbadd..663542d 100644 --- a/Sources/App/Middleware/ViewRoute+middleware.swift +++ b/Sources/App/Middleware/ViewRoute+middleware.swift @@ -14,10 +14,11 @@ private let viewRouteMiddleware: [any Middleware] = [ extension SiteRoute.View { var middleware: [any Middleware]? { switch self { + // TODO: Should pdf require authentication, just here now for testing. + case .project(.detail(_, .pdf)), .login, .signup, .test: + return nil case .project, .user: return viewRouteMiddleware - case .login, .signup, .test: - return nil } } } diff --git a/Sources/App/configure.swift b/Sources/App/configure.swift index ce48122..88c7611 100644 --- a/Sources/App/configure.swift +++ b/Sources/App/configure.swift @@ -114,6 +114,39 @@ extension SiteRoute { extension DuctSizes: Content {} +// FIX: Move +func handlePdf(_ projectID: Project.ID, on request: Request) async throws -> Response { + @Dependency(\.projectClient) var projectClient + + let html = try await projectClient.toHTML(projectID) + let url = "/tmp/\(projectID)" + try await request.fileio.writeFile(.init(string: html.renderFormatted()), at: "\(url).html") + + let process = Process() + let standardInput = Pipe() + let standardOutput = Pipe() + process.standardInput = standardInput + process.standardOutput = standardOutput + process.executableURL = URL(fileURLWithPath: "/bin/pandoc") + process.arguments = [ + "\(url).html", "--pdf-engine=weasyprint", "-f", "html", + "--css=Public/css/pdf.css", + "-o", "\(url).pdf", + ] + try process.run() + process.waitUntilExit() + + var headers = HTTPHeaders() + headers.add(name: .contentType, value: "application/octet-stream") + headers.add(name: .contentDisposition, value: "attachment") + + let response = try await request.fileio.asyncStreamFile(at: "\(url).pdf", mediaType: .pdf) + response.headers.replaceOrAdd(name: .contentType, value: "application/octet-stream") + response.headers.replaceOrAdd( + name: .contentDisposition, value: "attachment; filename=Duct-Calc.pdf") + return response +} + @Sendable private func siteHandler( request: Request, @@ -128,6 +161,9 @@ private func siteHandler( return try await apiController.respond(route, request: request) case .health: return HTTPStatus.ok + // FIX: Move + case .view(.project(.detail(let projectID, .pdf))): + return try await handlePdf(projectID, on: request) case .view(let route): return try await viewController.respond(route: route, request: request) } diff --git a/Sources/PdfClient/Request+html.swift b/Sources/PdfClient/Request+html.swift index afd2dba..357efff 100644 --- a/Sources/PdfClient/Request+html.swift +++ b/Sources/PdfClient/Request+html.swift @@ -20,7 +20,7 @@ struct PdfDocument: HTMLDocument { var body: some HTML { div { - h1(.class("headline")) { "Duct Calc" } + // h1(.class("headline")) { "Duct Calc" } h2 { "Project" } diff --git a/Sources/Styleguide/ResultView.swift b/Sources/Styleguide/ResultView.swift index b538182..ac4ab0a 100644 --- a/Sources/Styleguide/ResultView.swift +++ b/Sources/Styleguide/ResultView.swift @@ -69,7 +69,7 @@ public struct ErrorView: HTML, Sendable { div { h1(.class("text-xl font-bold text-error")) { "Oops: Error" } p { - "\(error)" + "\(error.localizedDescription)" } } } diff --git a/Sources/ViewController/Live.swift b/Sources/ViewController/Live.swift index dc1d10f..8b6c1f2 100644 --- a/Sources/ViewController/Live.swift +++ b/Sources/ViewController/Live.swift @@ -193,15 +193,9 @@ extension SiteRoute.View.ProjectRoute { case .frictionRate(let route): return await route.renderView(on: request, projectID: projectID) case .pdf: - // return await ResultView2 { - // try await projectClient.toHTML(projectID) - // } onError: { - // ErrorView2(error: $0) - // } - // return await ResultView { + // FIX: This should return a pdf to download or be wrapped in a + // result view. return try! await projectClient.toHTML(projectID) - // } - // fatalError() case .rooms(let route): return await route.renderView(on: request, projectID: projectID) }