feat: Fixes generation of html document, it now builds a latex document in the build directory that it then converts to html. Need to update tests.
This commit is contained in:
@@ -4,10 +4,10 @@ import DependenciesMacros
|
||||
import Foundation
|
||||
import ShellClient
|
||||
|
||||
public extension DependencyValues {
|
||||
extension DependencyValues {
|
||||
|
||||
/// Runs shell commands.
|
||||
var commandClient: CommandClient {
|
||||
public var commandClient: CommandClient {
|
||||
get { self[CommandClient.self] }
|
||||
set { self[CommandClient.self] = newValue }
|
||||
}
|
||||
@@ -67,7 +67,8 @@ public struct CommandClient: Sendable {
|
||||
in workingDirectory: String? = nil,
|
||||
_ arguments: [String]
|
||||
) async throws {
|
||||
try await runCommand(.init(
|
||||
try await runCommand(
|
||||
.init(
|
||||
arguments: arguments,
|
||||
quiet: quiet,
|
||||
shell: shell,
|
||||
@@ -161,14 +162,16 @@ extension CommandClient: DependencyKey {
|
||||
.init { options in
|
||||
@Dependency(\.asyncShellClient) var shellClient
|
||||
if !options.quiet {
|
||||
try await shellClient.foreground(.init(
|
||||
try await shellClient.foreground(
|
||||
.init(
|
||||
shell: .init(options.shell),
|
||||
environment: environment,
|
||||
in: options.workingDirectory,
|
||||
options.arguments
|
||||
))
|
||||
} else {
|
||||
try await shellClient.background(.init(
|
||||
try await shellClient.background(
|
||||
.init(
|
||||
shell: .init(options.shell),
|
||||
environment: environment,
|
||||
in: options.workingDirectory,
|
||||
@@ -184,12 +187,12 @@ extension CommandClient: DependencyKey {
|
||||
}
|
||||
|
||||
@_spi(Internal)
|
||||
public extension CommandClient {
|
||||
extension CommandClient {
|
||||
|
||||
/// Create a command client that can capture the arguments / options.
|
||||
///
|
||||
/// This is used for testing.
|
||||
static func capturing(_ client: CapturingClient) -> Self {
|
||||
public static func capturing(_ client: CapturingClient) -> Self {
|
||||
.init { options in
|
||||
await client.set(options)
|
||||
}
|
||||
@@ -198,7 +201,7 @@ public extension CommandClient {
|
||||
/// Captures the arguments / options passed into the command client's run commands.
|
||||
///
|
||||
@dynamicMemberLookup
|
||||
actor CapturingClient: Sendable {
|
||||
public actor CapturingClient: Sendable {
|
||||
public private(set) var options: RunCommandOptions?
|
||||
|
||||
public init() {}
|
||||
|
||||
@@ -12,9 +12,8 @@ extension PandocClient.RunOptions {
|
||||
) async throws -> String {
|
||||
@Dependency(\.commandClient) var commandClient
|
||||
@Dependency(\.logger) var logger
|
||||
@Dependency(\.playbookClient) var playbookClient
|
||||
|
||||
return try await commandClient.run(logging: loggingOptions, quiet: quiet, shell: shell) {
|
||||
// return try await commandClient.run(logging: loggingOptions, quiet: quiet, shell: shell) {
|
||||
let ensuredOptions = try await self.ensuredOptions(fileType)
|
||||
|
||||
let projectDirectory = self.projectDirectory ?? environment["PWD"]
|
||||
@@ -23,9 +22,57 @@ extension PandocClient.RunOptions {
|
||||
throw ProjectDirectoryNotSpecified()
|
||||
}
|
||||
|
||||
try await buildProject(fileType, projectDirectory, ensuredOptions)
|
||||
|
||||
let outputDirectory = self.outputDirectory ?? projectDirectory
|
||||
let outputPath = "\(outputDirectory)/\(ensuredOptions.ensuredExtensionFileName)"
|
||||
|
||||
let arguments = ensuredOptions.makeArguments(
|
||||
fileType: fileType,
|
||||
outputPath: outputPath,
|
||||
projectDirectory: projectDirectory
|
||||
)
|
||||
|
||||
logger.debug("Pandoc arguments: \(arguments)")
|
||||
return try await runCommand(arguments, outputPath)
|
||||
|
||||
// return (arguments, outputPath)
|
||||
// }
|
||||
}
|
||||
|
||||
/// Runs a shell command with the given arguments, returning the passed in output path
|
||||
/// so the command can be chained, if needed.
|
||||
///
|
||||
@_spi(Internal)
|
||||
@discardableResult
|
||||
public func runCommand(
|
||||
_ arguments: [String],
|
||||
_ outputPath: String
|
||||
) async throws -> String {
|
||||
@Dependency(\.commandClient) var commandClient
|
||||
@Dependency(\.logger) var logger
|
||||
logger.debug("Running shell command with arguments: \(arguments)")
|
||||
return try await commandClient.run(logging: loggingOptions, quiet: quiet, shell: shell) {
|
||||
(arguments, outputPath)
|
||||
}
|
||||
}
|
||||
|
||||
/// Build the project if necessary, before running the shell command that builds the final
|
||||
/// output file(s).
|
||||
///
|
||||
@_spi(Internal)
|
||||
public func buildProject(
|
||||
_ fileType: PandocClient.FileType,
|
||||
_ projectDirectory: String,
|
||||
_ ensuredOptions: EnsuredPandocOptions
|
||||
) async throws {
|
||||
@Dependency(\.logger) var logger
|
||||
@Dependency(\.playbookClient) var playbookClient
|
||||
|
||||
if shouldBuildProject {
|
||||
logger.debug("Building project...")
|
||||
try await playbookClient.run.buildProject(.init(
|
||||
try await playbookClient.run.buildProject(
|
||||
.init(
|
||||
projectDirectory: projectDirectory,
|
||||
shared: .init(
|
||||
extraOptions: nil,
|
||||
@@ -34,20 +81,21 @@ extension PandocClient.RunOptions {
|
||||
quiet: quiet,
|
||||
shell: shell
|
||||
)
|
||||
))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let outputDirectory = self.outputDirectory ?? projectDirectory
|
||||
let outputPath = "\(outputDirectory)/\(ensuredOptions.ensuredExtensionFileName)"
|
||||
|
||||
let arguments = ensuredOptions.makeArguments(
|
||||
// Build latex file pre-html, so that we can properly convert the latex document
|
||||
// into an html document.
|
||||
if fileType == .html {
|
||||
logger.debug("Building latex, pre-html conversion...")
|
||||
let outputPath = "\(ensuredOptions.buildDirectory)/Report.tex"
|
||||
let arguments = ensuredOptions.preHtmlLatexOptions.makeArguments(
|
||||
fileType: .latex,
|
||||
outputPath: outputPath,
|
||||
projectDirectory: projectDirectory
|
||||
)
|
||||
|
||||
logger.debug("Pandoc arguments: \(arguments)")
|
||||
|
||||
return (arguments, outputPath)
|
||||
try await runCommand(arguments, outputPath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +128,8 @@ extension PandocClient.FileType {
|
||||
|
||||
@_spi(Internal)
|
||||
public struct EnsuredPandocOptions: Equatable, Sendable {
|
||||
public static let latexFilename = "Report.tex"
|
||||
|
||||
public let buildDirectory: String
|
||||
public let extraOptions: [String]?
|
||||
public let files: [String]
|
||||
@@ -97,15 +147,30 @@ public struct EnsuredPandocOptions: Equatable, Sendable {
|
||||
return outputFileName
|
||||
}
|
||||
|
||||
public var preHtmlLatexOptions: Self {
|
||||
.init(
|
||||
buildDirectory: buildDirectory,
|
||||
extraOptions: extraOptions,
|
||||
files: files,
|
||||
includeInHeader: includeInHeader,
|
||||
outputFileName: Self.latexFilename,
|
||||
outputFileType: .latex,
|
||||
pdfEngine: nil
|
||||
)
|
||||
}
|
||||
|
||||
func makeArguments(
|
||||
fileType: PandocClient.FileType,
|
||||
outputPath: String,
|
||||
projectDirectory: String
|
||||
) -> [String] {
|
||||
var arguments = [PandocClient.Constants.pandocCommand]
|
||||
|
||||
if fileType != .html {
|
||||
arguments += includeInHeader.map {
|
||||
"--include-in-header=\(projectDirectory)/\(buildDirectory)/\($0)"
|
||||
}
|
||||
}
|
||||
|
||||
if let pdfEngine {
|
||||
arguments.append("--pdf-engine=\(pdfEngine)")
|
||||
@@ -117,9 +182,13 @@ public struct EnsuredPandocOptions: Equatable, Sendable {
|
||||
arguments.append(contentsOf: extraOptions)
|
||||
}
|
||||
|
||||
if fileType != .html {
|
||||
arguments += files.map {
|
||||
"\(projectDirectory)/\(buildDirectory)/\($0)"
|
||||
}
|
||||
} else {
|
||||
arguments.append("\(projectDirectory)/\(buildDirectory)/\(Self.latexFilename)")
|
||||
}
|
||||
|
||||
return arguments
|
||||
}
|
||||
@@ -145,15 +214,15 @@ public func ensurePandocOptions(
|
||||
}
|
||||
|
||||
@_spi(Internal)
|
||||
public extension PandocClient.FileType {
|
||||
func parsePdfEngine(
|
||||
extension PandocClient.FileType {
|
||||
public func parsePdfEngine(
|
||||
_ configuration: Configuration.Generate?,
|
||||
_ defaults: Configuration.Generate
|
||||
) -> String? {
|
||||
switch self {
|
||||
case .html, .latex:
|
||||
return nil
|
||||
case let .pdf(engine: engine):
|
||||
case .pdf(let engine):
|
||||
if let engine {
|
||||
return engine
|
||||
} else if let engine = configuration?.pdfEngine {
|
||||
@@ -168,8 +237,8 @@ public extension PandocClient.FileType {
|
||||
}
|
||||
|
||||
@_spi(Internal)
|
||||
public extension PandocClient.RunOptions {
|
||||
func parseFiles(
|
||||
extension PandocClient.RunOptions {
|
||||
public func parseFiles(
|
||||
_ configuration: Configuration.Generate?,
|
||||
_ defaults: Configuration.Generate
|
||||
) -> [String] {
|
||||
@@ -187,7 +256,7 @@ public extension PandocClient.RunOptions {
|
||||
}
|
||||
}
|
||||
|
||||
func parseIncludeInHeader(
|
||||
public func parseIncludeInHeader(
|
||||
_ configuration: Configuration.Generate?,
|
||||
_ defaults: Configuration.Generate
|
||||
) -> [String] {
|
||||
@@ -205,7 +274,7 @@ public extension PandocClient.RunOptions {
|
||||
}
|
||||
}
|
||||
|
||||
func parseOutputFileName(
|
||||
public func parseOutputFileName(
|
||||
_ configuration: Configuration.Generate?,
|
||||
_ defaults: Configuration.Generate
|
||||
) -> String {
|
||||
@@ -223,7 +292,7 @@ public extension PandocClient.RunOptions {
|
||||
}
|
||||
}
|
||||
|
||||
func parseBuildDirectory(
|
||||
public func parseBuildDirectory(
|
||||
_ configuration: Configuration.Generate?,
|
||||
_ defaults: Configuration.Generate
|
||||
) -> String {
|
||||
|
||||
@@ -4,14 +4,14 @@ import Dependencies
|
||||
import DependenciesMacros
|
||||
import Foundation
|
||||
|
||||
public extension DependencyValues {
|
||||
extension DependencyValues {
|
||||
|
||||
/// Represents interactions with the `pandoc` command line application.
|
||||
///
|
||||
/// The `pandoc` command line application is used to generate the final output
|
||||
/// documents from a home performance assessment project.
|
||||
///
|
||||
var pandocClient: PandocClient {
|
||||
public var pandocClient: PandocClient {
|
||||
get { self[PandocClient.self] }
|
||||
set { self[PandocClient.self] = newValue }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user