Moved BindingGenerator from gen html project. It makes more sense here.

This commit is contained in:
2025-10-25 00:06:22 -04:00
parent 58a8419984
commit 603a0aa0e3
141 changed files with 12738 additions and 7 deletions

View File

@@ -0,0 +1,33 @@
//
// FileManager+Ext.swift
// gen_html
//
// Created by Isaac Paul on 4/30/25.
//
import Foundation
extension FileManager {
//TODO: should also check if url is file
func listFiles(_ directory:URL, withLowercaseExtensions:[String] = [], recursive:Bool = false) throws -> [URL] {
let options:FileManager.DirectoryEnumerationOptions = recursive ? [] : [.skipsSubdirectoryDescendants]
let fileIterator = try self.contentsOfDirectory(at: directory, includingPropertiesForKeys: [.isDirectoryKey], options: options)
let filesOnly = fileIterator.filter { (url) -> Bool in
do {
let resourceValues = try url.resourceValues(forKeys: [.isDirectoryKey])
let isDirectory = resourceValues.isDirectory ?? true
if (isDirectory) {
return false
}
} catch { return false }
if withLowercaseExtensions.count > 0 {
let pathExt = url.pathExtension.lowercased()
let contains = withLowercaseExtensions.firstIndex(of: pathExt)
return contains != nil
}
return true
}
return filesOnly
}
}

View File

@@ -0,0 +1,43 @@
//
// String+Ext.swift
// gen_html
//
// Created by Isaac Paul on 9/25/25.
//
import Foundation
extension String {
init(readFromUrl:URL) throws {
let inputHandle = try FileHandle(forReadingFrom: readFromUrl)
guard let data = try inputHandle.readToEnd() else {
throw AppError("Empty input.")
}
guard let fileStr = String(data: data, encoding: .utf8) else {
throw AppError("Unable to decode data as utf-8 string")
}
self = fileStr
}
func uppercaseFirstLetter() -> String {
guard let firstLetter = self.first else { return self }
return firstLetter.uppercased() + self.dropFirst()
}
func fixPoorCharactersForVariables() -> String {
let firstPass = self.camelCaseBy("-")
let secondPass = firstPass.replacingOccurrences(of: "/", with: "_")
return secondPass
}
func camelCaseBy(_ c: Character) -> String {
let components = self.split(separator: c)
guard let first = components.first?.lowercased() else { return "" }
let rest = components.dropFirst().map { $0.capitalized }
let camelCase = ([first] + rest).joined()
return camelCase
}
}

View File

@@ -0,0 +1,68 @@
//
// Url+Ext.swift
// gen_html
//
// Created by Isaac Paul on 9/25/25.
//
import Foundation
extension URL {
enum FileType {
case directory
case regularFile
case other
}
func fetchFileType() throws -> FileType {
let values = try self.resourceValues(forKeys: [.isDirectoryKey, .isRegularFileKey])
if values.isDirectory == true {
return .directory
}
if values.isRegularFile == true {
return .regularFile
}
if self.hasDirectoryPath {
return .directory
}
return .other
}
func getRelativePathComponents(
to toFolder: URL, // URL A
) throws -> [String] {
// 1) Get path components of As directory
let aDirComponents = toFolder.pathComponents
// 2) Get path components of B
let bComponents = self.pathComponents
// Ensure B is actually a prefix of As directory
guard bComponents.count <= aDirComponents.count,
aDirComponents[0..<bComponents.count] == bComponents[0..<bComponents.count]
else {
// B is not a parent of As directory; just return destFolder
throw AppError("Url \(self.absoluteString) is not a relative path to \(toFolder.absoluteString)")
}
// 3) Compute the relative components from B to As directory
let relativeComponents = Array(aDirComponents[bComponents.count...])
return relativeComponents
}
func appendRelativePath(
from fromFolder: URL, // URL A
base baseFolder: URL // URL B
) throws -> URL {
let relativeComponents = try baseFolder.getRelativePathComponents(to: fromFolder)
// 4) Append them one by one onto C
var result = self
for comp in relativeComponents {
result.appendPathComponent(comp)
}
return result
}
}