diff --git a/Sources/Generator/Extensions/URL+Extensions.swift b/Sources/Generator/Extensions/URL+Extensions.swift index 9281cb5..ca460d1 100644 --- a/Sources/Generator/Extensions/URL+Extensions.swift +++ b/Sources/Generator/Extensions/URL+Extensions.swift @@ -50,4 +50,23 @@ extension URL { let attributes = try? FileManager.default.attributesOfItem(atPath: path) return (attributes?[.size] as? NSNumber)?.intValue } + + func resolvingFolderTraversal() -> URL? { + var components = [String]() + absoluteString.components(separatedBy: "/").forEach { part in + if part == ".." { + if !components.isEmpty { + _ = components.dropLast() + } else { + components.append("..") + } + return + } + if part == "." { + return + } + components.append(part) + } + return URL(string: components.joined(separator: "/")) + } } diff --git a/Sources/Generator/Files/Configuration.swift b/Sources/Generator/Files/Configuration.swift index 17e20b2..b610cfa 100644 --- a/Sources/Generator/Files/Configuration.swift +++ b/Sources/Generator/Files/Configuration.swift @@ -31,12 +31,12 @@ struct Configuration: Codable { /** The path to the directory where the root element metadata is located. */ - let contentPath: String + var contentPath: String /** The path where the generated website should be written. */ - let outputPath: String + var outputPath: String /** Create .md files for content pages, if they don't exist. @@ -62,6 +62,15 @@ struct Configuration: Codable { .init(fileURLWithPath: outputPath) } + mutating func adjustPathsRelative(to folder: URL) { + if !contentPath.hasPrefix("/") { + contentPath = folder.appendingPathComponent(contentPath).resolvingFolderTraversal()!.path + } + if !outputPath.hasPrefix("/") { + outputPath = folder.appendingPathComponent(outputPath).resolvingFolderTraversal()!.path + } + } + func printOverview() { print(" Source folder: \(contentDirectory.path)") print(" Output folder: \(outputDirectory.path)") diff --git a/Sources/Generator/run.swift b/Sources/Generator/run.swift index e11d3ee..3fe19ed 100644 --- a/Sources/Generator/run.swift +++ b/Sources/Generator/run.swift @@ -18,10 +18,11 @@ private func loadConfiguration(at configPath: String) -> Configuration? { print(" ") print(" Configuration file: \(configPath)") let configUrl = URL(fileURLWithPath: configPath) - let config: Configuration + var config: Configuration do { let data = try Data(contentsOf: configUrl) config = try JSONDecoder().decode(from: data) + config.adjustPathsRelative(to: configUrl.deletingLastPathComponent()) } catch { print(" Configuration error: \(error)") return nil