Skip to content

jeffhodsdon/SwiftResources

Repository files navigation

SwiftResources

License Bazel Swift

Type-safe resource accessors for Swift. Zero dependencies with a Bazel ruleset included.

Why?

  • Xcode independent — Works with Bazel, SPM, or CLI
  • No dependencies — During runtime or generation
  • Bazel supportswift_resources_library rule
  • Cross-platform — Accessors for UIKit, AppKit, and SwiftUI

Inspired by R.swift

Supported Resource Types

Generated code uses Resources as the default namespace (change via --module-name).

Fonts

Input: .ttf, .otf

// Fixed size
let font = Resources.fonts.lilexBold.font(size: 16)         // SwiftUI
let uiFont = Resources.fonts.lilexBold.uiFont(size: 16)     // UIKit
let nsFont = Resources.fonts.lilexBold.nsFont(size: 16)     // AppKit

// Dynamic Type
let scaledFont = Resources.fonts.lilexBold.font(size: 16, relativeTo: .body)
let scaledUIFont = Resources.fonts.lilexBold.uiFont(size: 28, relativeTo: .title1)

Images

Input: .png, .jpg, .jpeg, .pdf, .svg, .heic, or imagesets from .xcassets

let image = Resources.images.logo.image                     // SwiftUI
let uiImage = Resources.images.logo.uiImage                 // UIKit
let nsImage = Resources.images.logo.nsImage                 // AppKit

Colors

Input: colorsets from .xcassets

let color = Resources.colors.primary.color                  // SwiftUI
let uiColor = Resources.colors.primary.uiColor              // UIKit
let nsColor = Resources.colors.primary.nsColor              // AppKit

Files

Input: any file type (.json, .plist, .xml, .txt, etc.)

let url = Resources.files.config.url                        // URL?
let data = Resources.files.config.data                      // Data?

Localized Strings

Input: .xcstrings or .strings

let title = Resources.strings.localizable.welcomeTitle      // Simple string
let msg = Resources.strings.localizable.greeting("World")   // With argument
let items = Resources.strings.localizable.itemsCount(5)     // Pluralized

Requirements

  • Swift 5.9+
  • macOS 13+ (for CLI font name extraction via CoreText)
  • Bazel 7.x+ (for Bazel rules)

Installation

Bazel (BCR)

bazel_dep(name = "rules_swift_resources", version = "0.1.0")

Swift Package Manager

.package(url: "https://github.com/jeffhodsdon/SwiftResources.git", from: "0.1.0")

Usage

CLI

Swift:

swift build
.build/debug/sr generate --help

Bazel:

bazel run //:sr -- generate --help

Example:

sr generate \
  --fonts Resources/Fonts \
  --images Resources/Images \
  --xcassets Resources/Assets.xcassets \
  --files Resources/Data \
  --strings Resources/Localizable.xcstrings \
  --output Generated/Resources.swift \
  --module-name DesignSystem \
  --access-level public

CLI Options

Flag Default Description
--fonts <dir> Directories containing .ttf/.otf files (repeatable)
--images <dir> Directories containing image files (repeatable)
--xcassets <dir> Asset catalog directories (.xcassets) (repeatable)
--files <dir> Directories containing data files (repeatable)
--strings <path> String catalog (.xcstrings) or .strings files (repeatable)
--development-region <lang> Source language for .strings files (auto-detected for .xcstrings)
--output <path> stdout Output Swift file path
--module-name <name> Resources Generated enum namespace
--access-level <level> internal public or internal
--bundle <expr> BundleFinder Bundle expression (.module, .main, or custom)
--no-register-fonts Disable font registration code generation
--force-unwrap Generate non-optional accessors with force unwrap

Bazel

load("@rules_swift_resources//rules_swift_resources:defs.bzl", "swift_resources_library")

swift_resources_library(
    name = "DesignSystemResources",
    fonts = glob(["Fonts/**/*.ttf"]),
    images = glob(["Images/**/*.png"]),
    xcassets = glob(["Assets.xcassets/**"]),
    strings = ["Localizable.xcstrings"],
    module_name = "DesignSystem",
)

The macro creates a .resources filegroup for bundling:

swift_library(
    name = "MyApp",
    deps = [":DesignSystemResources"],  # Type-safe accessors
)

ios_application(
    name = "App",
    deps = [":MyApp"],
    resources = [":DesignSystemResources.resources"],  # Bundle the files
)

Note: swift_resources_library generates type-safe accessors but does not bundle resource files automatically. Use the .resources filegroup to include them in your app bundle.

License

Apache 2.0

About

Type-safe resource accessors for Swift. Lightweight. No dependencies. Bazel rules included.

Resources

License

Stars

Watchers

Forks

Packages

No packages published