Skip to content

Commit

Permalink
Fonts support (#20)
Browse files Browse the repository at this point in the history
* Update dependencies, initial support for fonts

* Don't use keypaths as functions

* Better indent ergonomics

* Encapsulate bundle access and clean up

* More cleanup

* Reorder to image - color - font - localization. Trim space-only lines.

* Improve README
  • Loading branch information
kaandedeoglu committed Dec 16, 2020
1 parent 3ada8be commit 8178d10
Show file tree
Hide file tree
Showing 14 changed files with 377 additions and 416 deletions.
6 changes: 0 additions & 6 deletions .travis.yml

This file was deleted.

16 changes: 8 additions & 8 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/tadija/AEXML",
"state": {
"branch": null,
"revision": "e4d517844dd03dac557e35d77a8e9ab438de91a6",
"version": "4.4.0"
"revision": "8623e73b193386909566a9ca20203e33a09af142",
"version": "4.5.0"
}
},
{
Expand All @@ -24,26 +24,26 @@
"repositoryURL": "https://github.com/kylef/Spectre.git",
"state": {
"branch": null,
"revision": "f14ff47f45642aa5703900980b014c2e9394b6e5",
"version": "0.9.0"
"revision": "f79d4ecbf8bc4e1579fbd86c3e1d652fb6876c53",
"version": "0.9.2"
}
},
{
"package": "swift-argument-parser",
"repositoryURL": "https://github.com/apple/swift-argument-parser",
"state": {
"branch": null,
"revision": "f6ac7b8118ff5d1bc0faee7f37bf6f8fd8f95602",
"version": "0.0.1"
"revision": "92646c0cdbaca076c8d3d0207891785b3379cbff",
"version": "0.3.1"
}
},
{
"package": "XcodeProj",
"repositoryURL": "https://github.com/tuist/xcodeproj.git",
"state": {
"branch": null,
"revision": "02e4ee305baf0ba23af7522210250d8275200122",
"version": "7.6.0"
"revision": "82bf5efcaa27e94ed8c761c1eb3e397b6dea82b9",
"version": "7.18.0"
}
}
]
Expand Down
324 changes: 121 additions & 203 deletions README.md

Large diffs are not rendered by default.

21 changes: 6 additions & 15 deletions Sources/Shark/ColorEnumBuilder.swift
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import Foundation

private enum ColorValue: Equatable, Comparable {
case color(name: String)
private struct ColorValue: Equatable, Comparable {
let name: String

func declaration(indentLevel: Int) -> String {
switch self {
case .color(let name):
return #"\#(String(indentLevel: indentLevel))public static var \#(name.casenameSanitized): UIColor { return UIColor(named: "\#(name)", in: \#(SharkEnumBuilder.topLevelEnumName).bundle, compatibleWith: nil)! }"#
}
return #"\#(String.indent(indentLevel))public static var \#(name.casenameSanitized): UIColor { return UIColor(named: "\#(name)", in: bundle, compatibleWith: nil)! }"#
}

static func <(lhs: ColorValue, rhs: ColorValue) -> Bool {
switch (lhs, rhs) {
case (.color(let leftName), .color(let rightName)):
return leftName < rightName
}
return lhs.name < rhs.name
}
}

Expand All @@ -26,13 +20,10 @@ enum ColorEnumBuilder {
static func colorEnumString(forFilesAtPaths paths: [String], topLevelName: String) throws -> String? {
let colorAssetPaths = try paths.flatMap { try FileManager.default.subpathsOfDirectory(atPath: $0).filter({ $0.pathExtension == Constants.colorSetExtension }) }
guard colorAssetPaths.isEmpty == false else { return nil }

var result = """
public enum \(topLevelName) {

"""
var result = "public enum \(topLevelName) {\n"
for name in colorAssetPaths.map({ $0.lastPathComponent.deletingPathExtension }).sorted() {
result += ColorValue.color(name: name).declaration(indentLevel: 1)
result += ColorValue(name: name).declaration(indentLevel: 1)
result += "\n"
}

Expand Down
49 changes: 49 additions & 0 deletions Sources/Shark/FontEnumBuilder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Foundation

private struct FontValue: Equatable, Comparable {
let methodName: String
let fontName: String

func declaration(indentLevel: Int) -> String {
#"\#(String.indent(indentLevel))public static func \#(methodName)(ofSize size: CGFloat) -> UIFont { return UIFont(name: "\#(fontName)", size: size)! }"#
}

static func <(lhs: FontValue, rhs: FontValue) -> Bool {
lhs.methodName < rhs.methodName
}
}

enum FontEnumBuilder {
static func fontsEnumString(forFilesAtPaths paths: [String], topLevelName: String) throws -> String? {
let fontValues: [FontValue] = paths.compactMap { path in
guard
let data = try? Data(contentsOf: URL(fileURLWithPath: path)),
let font = CGDataProvider(data: data as CFData).flatMap(CGFont.init),
let fullName = font.fullName as String?,
let postScriptName = font.postScriptName as String? else { return nil }

var components = fullName.split(separator: " ")
let first = components.removeFirst().lowercased()
let rest = components.map { $0.capitalized }
let methodName = ([first] + rest).joined()

return FontValue(methodName: methodName,
fontName: postScriptName)
}

guard fontValues.isEmpty == false else { return nil }

var result = """
public enum \(topLevelName) {
"""

for font in fontValues.sorted() {
result += font.declaration(indentLevel: 1)
result += "\n"
}

result += "}"
return result
}
}
66 changes: 22 additions & 44 deletions Sources/Shark/ImageEnumBuilder.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import Foundation

private enum ImageValue: Equatable, Comparable {
case namespace(name: String)
case image(caseName: String, value: String)
case namespace(name: String)

func declaration(withBody body: String = "", indentLevel: Int) throws -> String {
switch self {
case .image(let name, let value):
return #"\#(String(indentLevel: indentLevel))public static var \#(name): UIImage { return UIImage(named:"\#(value)", in: \#(SharkEnumBuilder.topLevelEnumName).bundle, compatibleWith: nil)! }"#
return #"\#(String.indent(indentLevel))public static var \#(name): UIImage { return UIImage(named:"\#(value)", in: bundle, compatibleWith: nil)! }"#
case .namespace(let name):
return #"""
\#(String(indentLevel: indentLevel))public enum \#(name) {
\#(String.indent(indentLevel))public enum \#(name) {
\#(body)
\#(String(indentLevel: indentLevel))}
\#(String.indent(indentLevel))}
"""#
}
Expand All @@ -31,6 +31,24 @@ private enum ImageValue: Equatable, Comparable {
}
}

extension ImageValue: SanitizableValue {
var name: String {
switch self {
case .namespace(let name), .image(let name, _):
return name
}
}

func underscoringName() -> ImageValue {
switch self {
case .image(let caseName, let value):
return .image(caseName: caseName.underscored, value: value)
case .namespace(let name):
return .namespace(name: name.underscored)
}
}
}

enum ImageEnumBuilder {
private enum Constants {
static let imageSetExtension = "imageset"
Expand Down Expand Up @@ -67,43 +85,3 @@ enum ImageEnumBuilder {
}
}
}

private extension Node where Element == ImageValue {
func sanitize() {
//If two children have the same name, or if a child has the same name with its parent, underscore
var modified = false
repeat {
modified = false
var countedSet = CountedSet<String>()
for child in children {
for _ in 0..<countedSet.count(for: child.name) {
child.underscoreName()
modified = true
}
countedSet.add(child.name)
if name == child.name {
child.underscoreName()
modified = true
}
}
} while modified

children.forEach { $0.sanitize() }
}

private var name: String {
switch value {
case .namespace(let name), .image(let name, _):
return name
}
}

private func underscoreName() {
switch value {
case .image(let caseName, let value):
self.value = .image(caseName: caseName.underscored, value: value)
case .namespace(let name):
self.value = .namespace(name: name.underscored)
}
}
}
76 changes: 27 additions & 49 deletions Sources/Shark/LocalizationEnumBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ private enum LocalizationValue: Comparable {
switch self {
case .namespace(let name):
result += #"""
\#(String(indentLevel: indentLevel))public enum \#(name) {
\#(String.indent(indentLevel))public enum \#(name) {
\#(body)
\#(String(indentLevel: indentLevel))}
\#(String.indent(indentLevel))}
"""#
case .localization(let name, let key, let value):
let translationComment = value.mapLines { "/// \($0)" }
Expand All @@ -73,7 +73,7 @@ private enum LocalizationValue: Comparable {
if interpolatedTypes.isEmpty == false {
result += interpolatedTypes.functionDeclaration(withName: name, key: key, indentLevel: indentLevel)
} else {
result += #"\#(String(indentLevel: indentLevel))public static var \#(name): String { return NSLocalizedString("\#(key)", bundle: \#(SharkEnumBuilder.topLevelEnumName).bundle, comment: "") }"#
result += #"\#(String.indent(indentLevel))public static var \#(name): String { return NSLocalizedString("\#(key)", bundle: bundle, comment: "") }"#
}
}
return result
Expand All @@ -87,10 +87,28 @@ private enum LocalizationValue: Comparable {
}
}

enum LocalizationBuilderError: Error {
extension LocalizationValue: SanitizableValue {
var name: String {
switch self {
case .namespace(let name), .localization(let name, _, _):
return name
}
}

func underscoringName() -> Self {
switch self {
case .localization(let name, let key, let value):
return .localization(name: name.underscored, key: key, value: value)
case .namespace(let name):
return .namespace(name: name.underscored)
}
}
}

enum LocalizationBuilderError: LocalizedError {
case invalidLocalizableStringsFile(path: String)
var localizedDescription: String {

var errorDescription: String? {
switch self {
case .invalidLocalizableStringsFile(let path):
return "Invalid .strings file at \(path)"
Expand Down Expand Up @@ -154,49 +172,9 @@ extension Array where Element == LocalizationValue.InterpolationType {
let formatValuesString = (1...count).map { "\(variableName)\($0)"}.joined(separator: ", ")

return #"""
\#(String(indentLevel: indentLevel))public static func \#(name)(\#(argumentsString)) -> String {
\#(String(indentLevel:indentLevel + 1))return String(format: NSLocalizedString("\#(key)", bundle: \#(SharkEnumBuilder.topLevelEnumName).bundle, comment: ""), \#(formatValuesString))
\#(String(indentLevel: indentLevel))}
\#(String.indent(indentLevel))public static func \#(name)(\#(argumentsString)) -> String {
\#(String.indent(indentLevel + 1))return String(format: NSLocalizedString("\#(key)", bundle: bundle, comment: ""), \#(formatValuesString))
\#(String.indent(indentLevel))}
"""#
}
}

private extension Node where Element == LocalizationValue {
func sanitize() {
//If two children have the same name, or if a children has the same name with a parent, underscore
var modified = false
repeat {
modified = false
var countedSet = CountedSet<String>()
for child in children {
for _ in 0..<countedSet.count(for: child.name) {
child.underscoreName()
modified = true
}
countedSet.add(child.name)
if name == child.name {
child.underscoreName()
modified = true
}
}
} while modified

children.forEach { $0.sanitize() }
}

private var name: String {
switch value {
case .localization(let name, _, _), .namespace(let name):
return name
}
}

private func underscoreName() {
switch value {
case .localization(let name, let key, let value):
self.value = .localization(name: name.underscored, key: key, value: value)
case .namespace(let name):
self.value = .namespace(name: name.underscored)
}
}
}
34 changes: 32 additions & 2 deletions Sources/Shark/Node.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Foundation

// A simple tree node
final class Node<Element> {
var value: Element
Expand Down Expand Up @@ -44,3 +42,35 @@ extension Node: Comparable where Element: Comparable {
return lhs.value < rhs.value
}
}

extension Node where Element: SanitizableValue {
func sanitize() {
//If two children have the same name, or if a children has the same name with a parent, underscore
var modified = false
repeat {
modified = false
var countedSet = CountedSet<String>()
for child in children {
for _ in 0..<countedSet.count(for: child.name) {
child.underscoreName()
modified = true
}
countedSet.add(child.name)
if name == child.name {
child.underscoreName()
modified = true
}
}
} while modified

children.forEach { $0.sanitize() }
}

private var name: String {
return value.name
}

private func underscoreName() {
value = value.underscoringName()
}
}
Loading

0 comments on commit 8178d10

Please sign in to comment.