Renamed the Path+Functions extension in the library target as PathProvider.

This commit is contained in:
Javier Cicchelli 2025-03-08 00:57:59 +01:00
parent 0ba84ca27a
commit 39a9523ac9
5 changed files with 153 additions and 50 deletions

View File

@ -1,49 +0,0 @@
enum Path {
// MARK: Functions
static func archivePath(from path: String) -> String {
let pathComponents = path.split(separator: .forwardSlash)
return pathComponents.count > 1
? .init(format: .Format.archiveDocC, String(pathComponents[1]))
: .empty
}
static func archiveName(from path: String) -> String {
let pathComponents = path.split(separator: .forwardSlash)
return pathComponents.count > 1
? .init(pathComponents[1]).lowercased()
: .empty
}
static func resourcePath(from path: String) -> String {
let matches = path.matches(of: /\//)
return matches.count > 2
? .init(path[matches[2].startIndex...])
: .forwardSlash
}
}
// MARK: - String+Constants
extension String {
static let empty = ""
static let forwardSlash = "/"
static let previousFolder = ".."
}
// MARK: - Character+Constants
private extension Character {
static let forwardSlash: Character = "/"
}
// MARK: - String+Formats
private extension String.Format {
static let archiveDocC = "/%@.doccarchive"
}

View File

@ -3,6 +3,8 @@ extension String {
enum Format {
/// A namespace that defines the format patterns used to generate relative path representations.
enum Path {
/// A representation of the format pattern used to generate relative paths that starts with the `/` string and finishes with the `.doccarchive` string.
static let archive = "/%@.doccarchive"
/// A representation of the format pattern used to generate relative paths that starts with the `/data` string.
static let data = "/data/%@"
/// A representation of the format pattern used to generate relative paths that starts with the `/docs` string.

View File

@ -1,4 +1,4 @@
/// A protocol that provides a relative path representation.
/// A type that provides a relative path representation.
protocol Pathable {
// MARK: Properties

View File

@ -0,0 +1,57 @@
/// A type that provides data extraction and manipulation functions from relative path representations.
enum PathProvider {
// MARK: Functions
/// Extracts the root *DocC* archive relative path from a given URL relative path.
///
/// Given that the provided URL relative path is expected to have the prefix `/archives/archive-name`, then a root *DocC* archive generated out of the
/// archive name obtained from the URL relative path is returned. Otherwise, an empty string is returned.
///
/// - Parameter path: A URL relative path from where to extract data.
/// - Returns: A URL relative path to a root *DocC* archive or an empty string .
static func archivePath(from path: String) -> String {
let pathComponents = path.split(separator: .forwardSlash)
return pathComponents.count > 1
? .init(format: .Format.Path.archive, String(pathComponents[1]))
: .empty
}
/// Extracts the name of the *DocC* archive from a given URL relative path.
///
/// Given that the provided URL relative path is expected to have the prefix `/archives/archive-name`, then a lowercased archive name from the URL
/// relative path is returned. Otherwise, an empty string is returned.
///
/// - Parameter path: A URL relative path from where to extract data.
/// - Returns: A lowercased name of the archive or an empty string.
static func archiveName(from path: String) -> String {
let pathComponents = path.split(separator: .forwardSlash)
return pathComponents.count > 1
? .init(pathComponents[1]).lowercased()
: .empty
}
/// Extracts the name of the *DocC* archive from a given URL relative path.
///
/// Given that the provided URL relative path is expected to have the format `/archives/archive-name/path/to/resource`, then the path to a
/// resource extracted from the URL relative path is returned. Otherwise, a forward slash string is returned.
///
/// - Parameter path: A URL relative path from where to extract data.
/// - Returns: A URL relative path to a resource or a forward slash.
static func resourcePath(from path: String) -> String {
let matches = path.matches(of: /\//)
return matches.count > 2
? .init(path[matches[2].startIndex...])
: .forwardSlash
}
}
// MARK: - Character+Constants
private extension Character {
static let forwardSlash: Character = "/"
}

View File

@ -0,0 +1,93 @@
import Testing
@testable import AppLibrary
@Suite("PathProvider", .tags(.provider))
struct PathProviderTests {
// MARK: Functions tests
@Test(arguments: zip([String].pathURLs, [String].nameArchives))
func archiveName(
from path: String,
expects name: String
) async throws {
// GIVEN
// WHEN
let result = PathProvider.archiveName(from: path)
// THEN
#expect(result == name)
}
@Test(arguments: zip([String].pathURLs, [String].pathArchives))
func archivePath(
from path: String,
expects archive: String
) async throws {
// GIVEN
// WHEN
let result = PathProvider.archivePath(from: path)
// THEN
#expect(result == archive)
}
@Test(arguments: zip([String].pathURLs, [String].pathResources))
func resourcePath(
from path: String,
expects resource: String
) async throws {
// GIVEN
// WHEN
let result = PathProvider.resourcePath(from: path)
// THEN
#expect(result == resource)
}
}
// MARK: - Collection+Strings
private extension Collection where Element == String {
// MARK: Properties
static var nameArchives: [Element] {[
.empty,
.empty,
.empty,
"somearchive",
"somearchive",
"somearchive"
]}
static var pathArchives: [Element] {[
.empty,
.empty,
.empty,
"/SomeArchive.doccarchive",
"/SomeArchive.doccarchive",
"/SomeArchive.doccarchive"
]}
static var pathResources: [Element] {[
.forwardSlash,
.forwardSlash,
.forwardSlash,
.forwardSlash,
.forwardSlash,
"/path/to/resource"
]}
static var pathURLs: [Element] {[
.empty,
"/archives",
"/archives/",
"/archives/SomeArchive",
"/archives/SomeArchive/",
"/archives/SomeArchive/path/to/resource"
]}
}