Skip to content

Commit

Permalink
feat: delete inputType (automatic inference from string) Add some opt…
Browse files Browse the repository at this point in the history
…ions.
  • Loading branch information
fummicc1 committed Nov 6, 2024
1 parent 6fab897 commit f457b37
Showing 1 changed file with 107 additions and 113 deletions.
220 changes: 107 additions & 113 deletions Sources/Csv2ImgCmd/command.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,31 @@ import Csv2ImgCore
import Foundation
import PDFKit

/// Csv resource type
public enum InputType: EnumerableFlag {
/// The local input-type
///
/// If you have a csv file on your computer, you cloud use this flag with `--local`, `-l`.
///
/// ```shell
/// ./Csv2ImgCmd --local ~/Downloads/sample.csv ./output.csv
/// ```
case local
/// The network input-type
///
/// If you would like to convert csv file on the internet, you cloud use this flag with `--network`, `-n`.
///
/// ```shell
/// ./Csv2ImgCmd --network \
/// https://raw.githubusercontent.com/fummicc1/csv2img/main/Sources/Csv2ImgCmd/Resources/sample_1.csv \
/// output.png
/// ```
case network

public static func name(
for value: InputType
) -> NameSpecification {
switch value {
case .local:
return [
.customLong(
"local"
),
.short,
]
case .network:
return [
.customLong(
"network"
),
.short,
]
}
}
}

/// Coomand line interface `Csv2Img`
///
///
/// If you have a csv file on your computer, you cloud use this flag with `--local`, `-l`.
///
/// ```shell
/// ./Csv2ImgCmd --local ~/Downloads/sample.csv ./output.png
/// ./Csv2ImgCmd ~/Downloads/sample.csv --output ./output.png
/// ```
///
/// If you would like to convert csv file on the internet, you cloud use this flag with `--network`, `-n`.
/// If you would like to convert csv file on the internet, you cloud just pass the url with prefix https:// or http:// such as https://example.com/
///
/// ```shell
/// ./Csv2ImgCmd --network \
/// https://raw.githubusercontent.com/fummicc1/csv2img/main/Sources/Csv2ImgCmd/Resources/sample_1.csv \
/// output.png
/// ./Csv2ImgCmd https://raw.githubusercontent.com/fummicc1/csv2img/main/Fixtures/sample_1.csv \
/// --output output.png
/// ```
@main
public struct Csv2Img: AsyncParsableCommand {

static let version: String = "1.9.1"

public static var configuration: CommandConfiguration {
CommandConfiguration(
commandName: "csv2img",
abstract: "Generate image from csv with png-format",
version: "1.4.0",
version: version,
shouldDisplay: true,
helpNames: [
.long,
Expand All @@ -78,99 +37,134 @@ public struct Csv2Img: AsyncParsableCommand {
)
}

@Flag(
help: "Csv file type. Choose either `local` or `network`"
@Option(
name: .shortAndLong,
help: "Export type. Choose either `pdf` or `png`"
)
public var inputType: InputType

@Option
public var exportType: Csv.ExportType = .pdf

@Argument(
help: "Input. csv absolute-path or url on the internet"
)
public var input: String

@Argument(
@Option(
name: .shortAndLong,
help: "Output. Specify local path."
)
public var output: String

public init() {
@Flag(
name: .shortAndLong,
help: "Print the version of csv2img"
)
public var version: Bool = false

@Option(
name: .shortAndLong,
help: "Specify the font size"
)
public var fontSize: Double = 12

@Option(
name: .shortAndLong,
help: "Paper size for PDF export (a4, b4, b3, etc). Default is b3"
)
public var paperSize: String = "b3"

@Option(
name: .shortAndLong,
help: "Page orientation for PDF (portrait/landscape). Default is landscape"
)
public var orientation: String = "landscape"

public init() {}

public func validate() throws {
if !input.hasPrefix("http") && !FileManager.default.fileExists(atPath: input) {
throw ValidationError("Input file does not exist at path: \(input)")
}

let outputDir = (output as NSString).deletingLastPathComponent
if !FileManager.default.fileExists(atPath: outputDir) {
throw ValidationError("Output directory does not exist: \(outputDir)")
}

let outputExtension = (output as NSString).pathExtension.lowercased()
switch exportType {
case .pdf where outputExtension != "pdf":
throw ValidationError("Output file extension should be .pdf when export type is PDF")
case .png where outputExtension != "png":
throw ValidationError("Output file extension should be .png when export type is PNG")
default:
break
}
}

public func run() async throws {
if version {
print("csv2img version \(Self.version)")
return
}

print("🚀 Starting conversion process...")

let csv: Csv
switch inputType {
case .local:
csv = try Csv.loadFromDisk(
URL(
fileURLWithPath: input
)
)
case .network:
guard
let url = URL(
string: input
)
else {
print(
"Invalid URL: \(input)."
)
return
if input.hasPrefix("http://") || input.hasPrefix("https://") {
print("📥 Downloading CSV from URL...")
guard let url = URL(string: input) else {
throw ValidationError("Invalid URL: \(input)")
}
csv = try Csv.loadFromNetwork(
url
)
csv = try Csv.loadFromNetwork(url)
} else {
print("📂 Reading local CSV file...")
csv = try Csv.loadFromDisk(URL(fileURLWithPath: input))
}

print("🔄 Processing CSV data...")

if exportType == .pdf {
let orientation: PdfSize.Orientation =
self.orientation.lowercased() == "portrait" ? .portrait : .landscape
let size = PdfSize(rawValue: paperSize.lowercased()) ?? .b3

await csv.update(
pdfMetadata: .init(
size: size,
orientation: orientation
))
print("📄 Configured PDF settings: \(paperSize) - \(orientation)")
}
await csv.update(pdfMetadata: .init(size: .b3, orientation: .landscape))

print("⚙️ Generating \(exportType) file...")

let exportable = try await csv.generate(
fontSize: 12,
fontSize: fontSize,
exportType: exportType,
style: .random()
).base
let outputURL = URL(
fileURLWithPath: output
)
if !FileManager.default.fileExists(
atPath: output
) {
FileManager.default.createFile(
atPath: output,
contents: Data()
)
}

print("💾 Saving file...")
try await saveExportable(exportable, to: URL(fileURLWithPath: output))

print("\n✅ Successfully generated \(exportType) file!")
print("📁 Output: \(output)")
}

private func saveExportable(_ exportable: any CsvExportable, to url: URL) async throws {
switch exportable {
case let pdf as PDFDocument:
let isSuccessful = pdf.write(
to: outputURL
)
if !isSuccessful {
throw PdfMakingError.failedToSavePdf(
at: outputURL.absoluteString
)
if !pdf.write(to: url) {
throw PdfMakingError.failedToSavePdf(at: url.absoluteString)
}
print(
"Succeed generating pdf from csv!"
)
case let image as CGImage:
let data = image.convertToData()
try data?.write(
to: outputURL
)
print(
"Succeed generating image from csv!"
)
guard let data = image.convertToData() else {
throw ValidationError("Failed to convert image to data")
}
try data.write(to: url)
default:
fatalError(
"unsupported exportable data."
)
throw ValidationError("Unsupported export type")
}
print(
"Output path: ",
outputURL.absoluteString
)
}
}

Expand Down

0 comments on commit f457b37

Please sign in to comment.