nearfri/xcresource
**XCResource** is a tool that allows you to efficiently and safely manage resources (localized strings, fonts, and other files) in Xcode projects.
Features
1. Type-Safe Resource Code Generation
- Generates type-safe Swift code for localized strings, fonts, and other files.
2. Flexible Configuration and Integration
- Supports Swift Package Manager for easy integration.
- Enables customized code generation using configuration files.
- Easily executable via Swift Package Plugin.
Getting Started
1. Adding XCResource to Your Project
Add to Package.swift
dependencies: [
.package(url: "https://github.com/nearfri/XCResource.git", from: "<version>"),
// OR
.package(url: "https://github.com/nearfri/XCResource-plugin.git", from: "<version>"),
],Recommendation: Use XCResource-plugin to take advantage of the precompiled binary executable.
Create a Configuration File (xcresource.json)
Add an xcresource.json file to your project. The plugin reads this file and generates Swift code every time it runs.
Supported paths for the configuration file:
${PROJECT_DIR}/xcresource.json${PROJECT_DIR}/.xcresource.json${PROJECT_DIR}/Configs/xcresource.json${PROJECT_DIR}/Scripts/xcresource.json
2. Managing Localized Strings
xcresource provides multiple subcommands. Among them, xcstrings2swift parses a String Catalog (.xcstrings) and generates LocalizedStringResource constants.
https://github.com/user-attachments/assets/16073e8f-9ad9-4e9c-b945-d542efd656f7
Configuration (xcresource.json)
{
"commands": [
{
"commandName": "xcstrings2swift",
"catalogPath": "Sources/Resources/Resources/Localizable.xcstrings",
"bundle": ".atURL(Bundle.module.bundleURL)",
"swiftFilePath": "Sources/Resources/ResourceAccess/LocalizedStringResource+.swift"
}
]
}Generated Code
public extension LocalizedStringResource {
/// \"\\(arg1)\" will be deleted.\
/// This action cannot be undone.
static func alertDeleteFile(_ arg1: String) -> Self {
.init("alert_delete_file",
defaultValue: """
\"\(arg1)\" will be deleted.
This action cannot be undone.
""",
bundle: .atURL(Bundle.module.bundleURL))
}
/// Done
static var commonDone: Self {
.init("common_done",
defaultValue: "Done",
bundle: .atURL(Bundle.module.bundleURL))
}
}(Function names and parameter names can be customized if they match the localization key and function signature.)
Usage
Text(.commonDone)3. Font Code Generation
fonts2swift generates Swift code for fonts.
https://github.com/user-attachments/assets/ae09a571-3ee8-450e-84c2-39341fe203d2
Configuration (xcresource.json)
{
"commands": [
{
"commandName": "fonts2swift",
"resourcesPath": "Sources/Resources/Resources",
"swiftFilePath": "Sources/Resources/ResourceAccess/FontResource.swift",
"resourceTypeName": "FontResource",
"resourceListName": "all",
"transformsToLatin": true,
"stripsCombiningMarks": true,
"preservesRelativePath": true,
"bundle": "Bundle.module",
"accessLevel": "public"
}
]
}Generated Code
public struct FontResource: Hashable, Sendable {
public let fontName: String
public let familyName: String
public let style: String
public let relativePath: String
public let bundle: Bundle
...
}
public extension FontResource {
static let all: [FontResource] = [
// Cambria
.cambriaRegular,
// Open Sans
.openSansBold,
]
}
public extension FontResource {
// MARK: Cambria
static let cambriaRegular: FontResource = .init(
fontName: "Cambria",
familyName: "Cambria",
style: "Regular",
relativePath: "Fonts/Cambria.ttc",
bundle: Bundle.module)
// MARK: Open Sans
static let openSansBold: FontResource = .init(
fontName: "OpenSans-Bold",
familyName: "Open Sans",
style: "Bold",
relativePath: "Fonts/OpenSans/OpenSans-Bold.ttf",
bundle: Bundle.module)
}Usage
Font.custom(.openSansBold, size: 16)4. File Code Generation
files2swift generates Swift code for files such as JSON.
Configuration (xcresource.json)
{
"commands": [
{
"commandName": "files2swift",
"resourcesPath": "Sources/Resources/Resources/Lotties",
"filePattern": "(?i)\\.json$",
"swiftFilePath": "Sources/Resources/ResourceAccess/LottieResource.swift",
"resourceTypeName": "LottieResource",
"preservesRelativePath": true,
"relativePathPrefix": "Lotties",
"bundle": "Bundle.module",
"accessLevel": "public"
}
]
}Generated Code
public struct LottieResource: Hashable, Sendable {
public let relativePath: String
public let bundle: Bundle
...
}
extension LottieResource {
public static let hello: LottieResource = .init(
relativePath: "Lotties/hello.json",
bundle: Bundle.module)
}Usage
LottieView(.hello)Commands
| Command | Description | |----------------------|--------------------------------------------------------------| | xcstrings2swift | Scans .xcstrings file and generates code. | | fonts2swift | Scans font directory and generates code. | | files2swift | Scans directory for matching files and generates code. | | xcassets2swift | Scans .xcassets directory and generates code. |
Example
This repository includes an example of using the plugin.
Architecture
graph TD
subgraph Plugin
P["Generate Resource Code<br/><i>plugin</i>"]
end
subgraph Executable
CLI["xcresource<br/><i>executableTarget</i>"]
end
subgraph Command
CMD["XCResourceCommand<br/><i>target</i>"]
end
subgraph "Core Modules"
LOC["LocStringResourceGen"]
FONT["FontResourceGen"]
FILE["FileResourceGen"]
ASSET["AssetResourceGen"]
UTIL["XCResourceUtil"]
end
subgraph "External Dependencies"
AP["ArgumentParser<br/><i>swift-argument-parser</i>"]
SS["SwiftSyntax<br/>SwiftParser<br/>SwiftSyntaxBuilder<br/>SwiftRefactor<br/><i>swift-syntax</i>"]
ST["StrixParsers<br/><i>Strix</i>"]
end
P --> CLI
CLI --> CMD
CMD --> AP
CMD --> LOC
CMD --> FONT
CMD --> FILE
CMD --> ASSET
CMD --> UTIL
LOC --> SS
LOC --> ST
LOC --> UTIL
FONT --> UTIL
FILE --> UTIL
ASSET --> UTIL
style P fill:#e8f5e9,stroke:#4caf50,color:#000000
style CLI fill:#fff3e0,stroke:#ff9800,color:#000000
style CMD fill:#e3f2fd,stroke:#2196f3,color:#000000
style LOC fill:#fce4ec,stroke:#e91e63,color:#000000
style FONT fill:#f3e5f5,stroke:#9c27b0,color:#000000
style FILE fill:#f3e5f5,stroke:#9c27b0,color:#000000
style ASSET fill:#f3e5f5,stroke:#9c27b0,color:#000000
style UTIL fill:#fffde7,stroke:#fbc02d,color:#000000
style AP fill:#eceff1,stroke:#607d8b,color:#000000
style SS fill:#eceff1,stroke:#607d8b,color:#000000
style ST fill:#eceff1,stroke:#607d8b,color:#000000Documentation
For more information about the plugin, check the documentation on Swift Package Index. - XCResource Documentation - Getting Started - Integrating XCResource into a Swift Package - Generating LocalizedStringResource - Generating FontResource - Advanced - Configuration File Format
License
XCResource is distributed under the MIT license. For more details, see the LICENSE file.
Package Metadata
Repository: nearfri/xcresource
Default branch: main
README: README.md