Skip to content

Commit

Permalink
Merge pull request #41 from hhru/post-processor-path
Browse files Browse the repository at this point in the history
Стиль названия для изображений
  • Loading branch information
timbaev authored Sep 5, 2023
2 parents b439547 + e9e9958 commit 0f93e5b
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 40 deletions.
26 changes: 25 additions & 1 deletion Sources/FigmaGen/Commands/ImagesCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,15 @@ final class ImagesCommand: AsyncExecutableCommand, GenerationConfigurableCommand
"""
)

let namingStyle = Key<String>(
"--naming-style",
"-s",
description: """
Optional image output naming style, can be 'camelCase' or 'snakeCase'.
Defaults to 'camelCase'.
"""
)

// MARK: - Initializers

init(generator: ImagesGenerator) {
Expand Down Expand Up @@ -191,6 +200,20 @@ final class ImagesCommand: AsyncExecutableCommand, GenerationConfigurableCommand
} ?? [.none]
}

private func resolveNamingStyle() -> ImageNamingStyle {
switch namingStyle.value {
case nil:
return .camelCase

case let rawNamingStyle?:
guard let format = ImageNamingStyle(rawValue: rawNamingStyle) else {
fail(message: "Failed to generated images: Invalid naming style (\(rawNamingStyle))")
}

return format
}
}

private func resolveImagesConfiguration() -> ImagesConfiguration {
ImagesConfiguration(
generatation: generationConfiguration,
Expand All @@ -202,7 +225,8 @@ final class ImagesCommand: AsyncExecutableCommand, GenerationConfigurableCommand
onlyExportables: onlyExportables.value,
useAbsoluteBounds: useAbsoluteBounds.value,
preserveVectorData: preserveVectorData.value,
groupByFrame: groupByFrame.value
groupByFrame: groupByFrame.value,
namingStyle: resolveNamingStyle()
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ extension ImagesConfiguration {
onlyExportables: onlyExportables,
useAbsoluteBounds: useAbsoluteBounds,
preserveVectorData: preserveVectorData,
groupByFrame: groupByFrame
groupByFrame: groupByFrame,
namingStyle: namingStyle
)
}
}
10 changes: 8 additions & 2 deletions Sources/FigmaGen/Models/Configuration/ImagesConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct ImagesConfiguration: Decodable {
case useAbsoluteBounds
case preserveVectorData
case groupByFrame
case namingStyle
}

// MARK: - Instance Properties
Expand All @@ -28,6 +29,7 @@ struct ImagesConfiguration: Decodable {
let useAbsoluteBounds: Bool
let preserveVectorData: Bool
let groupByFrame: Bool
let namingStyle: ImageNamingStyle

// MARK: - Initializers

Expand All @@ -41,7 +43,8 @@ struct ImagesConfiguration: Decodable {
onlyExportables: Bool,
useAbsoluteBounds: Bool,
preserveVectorData: Bool,
groupByFrame: Bool
groupByFrame: Bool,
namingStyle: ImageNamingStyle
) {
self.generatation = generatation
self.assets = assets
Expand All @@ -53,6 +56,7 @@ struct ImagesConfiguration: Decodable {
self.useAbsoluteBounds = useAbsoluteBounds
self.preserveVectorData = preserveVectorData
self.groupByFrame = groupByFrame
self.namingStyle = namingStyle
}

init(from decoder: Decoder) throws {
Expand All @@ -68,6 +72,7 @@ struct ImagesConfiguration: Decodable {
useAbsoluteBounds = try container.decodeIfPresent(forKey: .useAbsoluteBounds) ?? false
preserveVectorData = try container.decodeIfPresent(forKey: .preserveVectorData) ?? false
groupByFrame = try container.decodeIfPresent(forKey: .groupByFrame) ?? false
namingStyle = try container.decodeIfPresent(forKey: .namingStyle) ?? .camelCase

generatation = try GenerationConfiguration(from: decoder)
}
Expand All @@ -85,7 +90,8 @@ struct ImagesConfiguration: Decodable {
onlyExportables: onlyExportables,
useAbsoluteBounds: useAbsoluteBounds,
preserveVectorData: preserveVectorData,
groupByFrame: groupByFrame
groupByFrame: groupByFrame,
namingStyle: namingStyle
)
}
}
9 changes: 9 additions & 0 deletions Sources/FigmaGen/Models/Images/ImageNamingStyle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation

enum ImageNamingStyle: String, Codable {

// MARK: - Enumeration Cases

case camelCase
case snakeCase
}
1 change: 1 addition & 0 deletions Sources/FigmaGen/Models/Parameters/ImagesParameters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ struct ImagesParameters {
let useAbsoluteBounds: Bool
let preserveVectorData: Bool
let groupByFrame: Bool
let namingStyle: ImageNamingStyle
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,49 @@ final class DefaultImageAssetsProvider: ImageAssetsProvider, ImagesFolderPathRes

// MARK: - Instance Methods

private func resolveName(
for node: ImageRenderedNode,
setNode: ImageComponentSetRenderedNode,
namingStyle: ImageNamingStyle
) -> String {
let name = setNode.isSingleComponent ? node.base.name : "\(setNode.name) \(node.base.name)"

switch namingStyle {
case .camelCase:
return name.camelized

case .snakeCase:
return name.snakeCased
}
}

private func makeAsset(
for node: ImageRenderedNode,
setNode: ImageComponentSetRenderedNode,
format: ImageFormat,
preserveVectorData: Bool,
groupByFrame: Bool,
parameters: ImagesParameters,
folderPath: Path
) -> ImageAsset {
let name = setNode.isSingleComponent ? node.base.name.camelized : "\(setNode.name) \(node.base.name)".camelized
let folderPath = resolveFolderPath(groupByFrame: groupByFrame, setNode: setNode, folderPath: folderPath)
let name = resolveName(for: node, setNode: setNode, namingStyle: parameters.namingStyle)

let folderPath = resolveFolderPath(
groupByFrame: parameters.groupByFrame,
setNode: setNode,
folderPath: folderPath
)

let filePaths = node.urls.keys.reduce(into: [:]) { result, scale in
result[scale] = folderPath
.appending(fileName: name, extension: AssetImageSet.pathExtension)
.appending(fileName: name.appending(scale.fileNameSuffix), extension: format.fileExtension)
.appending(fileName: name.appending(scale.fileNameSuffix), extension: parameters.format.fileExtension)
.string
}

return ImageAsset(name: name, filePaths: filePaths, preserveVectorData: preserveVectorData)
return ImageAsset(name: name, filePaths: filePaths, preserveVectorData: parameters.preserveVectorData)
}

private func makeAssets(
for nodes: [ImageComponentSetRenderedNode],
format: ImageFormat,
preserveVectorData: Bool,
groupByFrame: Bool,
parameters: ImagesParameters,
folderPath: Path
) -> [ImageComponentSetAsset] {
nodes.map { setNode in
Expand All @@ -54,9 +71,7 @@ final class DefaultImageAssetsProvider: ImageAssetsProvider, ImagesFolderPathRes
assets[node] = makeAsset(
for: node,
setNode: setNode,
format: format,
preserveVectorData: preserveVectorData,
groupByFrame: groupByFrame,
parameters: parameters,
folderPath: folderPath
)
}
Expand Down Expand Up @@ -130,17 +145,13 @@ final class DefaultImageAssetsProvider: ImageAssetsProvider, ImagesFolderPathRes

func saveImages(
nodes: [ImageComponentSetRenderedNode],
format: ImageFormat,
preserveVectorData: Bool,
groupByFrame: Bool,
parameters: ImagesParameters,
in folderPath: String
) -> Promise<[ImageComponentSetAsset]> {
perform(on: DispatchQueue.global(qos: .userInitiated)) {
self.makeAssets(
for: nodes,
format: format,
preserveVectorData: preserveVectorData,
groupByFrame: groupByFrame,
parameters: parameters,
folderPath: Path(folderPath)
)
}.nest { assets in
Expand All @@ -152,7 +163,7 @@ final class DefaultImageAssetsProvider: ImageAssetsProvider, ImagesFolderPathRes
)
}
}.then { assets in
try self.saveAssetFolders(assets: assets, groupByFrame: groupByFrame, in: folderPath)
try self.saveAssetFolders(assets: assets, groupByFrame: parameters.groupByFrame, in: folderPath)
}.then {
self.saveImageFiles(assets: assets)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ protocol ImageAssetsProvider {

func saveImages(
nodes: [ImageComponentSetRenderedNode],
format: ImageFormat,
preserveVectorData: Bool,
groupByFrame: Bool,
parameters: ImagesParameters,
in folderPath: String
) -> Promise<[ImageComponentSetAsset]>
}
15 changes: 6 additions & 9 deletions Sources/FigmaGen/Providers/Images/DefaultImagesProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,13 @@ final class DefaultImagesProvider: ImagesProvider {

private func saveAssetImagesIfNeeded(
nodes: [ImageComponentSetRenderedNode],
format: ImageFormat,
preserveVectorData: Bool,
groupByFrame: Bool,
parameters: ImagesParameters,
in assets: String?
) -> Promise<[ImageComponentSetAsset]> {
assets.map { folderPath in
imageAssetsProvider.saveImages(
nodes: nodes,
format: format,
preserveVectorData: preserveVectorData,
groupByFrame: groupByFrame,
parameters: parameters,
in: folderPath
)
} ?? .value([])
Expand All @@ -170,6 +166,7 @@ final class DefaultImagesProvider: ImagesProvider {
groupByFrame: Bool,
format: ImageFormat,
postProcessor: String?,
namingStyle: ImageNamingStyle,
in resources: String?
) -> Promise<[ImageRenderedNode: ImageResource]> {
resources.map { folderPath in
Expand All @@ -178,6 +175,7 @@ final class DefaultImagesProvider: ImagesProvider {
groupByFrame: groupByFrame,
format: format,
postProcessor: postProcessor,
namingStyle: namingStyle,
in: folderPath
)
} ?? .value([:])
Expand All @@ -190,16 +188,15 @@ final class DefaultImagesProvider: ImagesProvider {
when(
fulfilled: self.saveAssetImagesIfNeeded(
nodes: nodes,
format: parameters.format,
preserveVectorData: parameters.preserveVectorData,
groupByFrame: parameters.groupByFrame,
parameters: parameters,
in: parameters.assets
),
self.saveResourceImagesIfNeeded(
nodes: nodes,
groupByFrame: parameters.groupByFrame,
format: parameters.format,
postProcessor: parameters.postProcessor,
namingStyle: parameters.namingStyle,
in: parameters.resources
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,31 @@ final class DefaultImageResourcesProvider: ImageResourcesProvider, ImagesFolderP

// MARK: - Instance Methods

private func resolveFileName(
for node: ImageRenderedNode,
setNode: ImageComponentSetRenderedNode,
namingStyle: ImageNamingStyle
) -> String {
let fileName = setNode.isSingleComponent ? node.base.name : "\(setNode.name) \(node.base.name)"

switch namingStyle {
case .camelCase:
return fileName.camelized

case .snakeCase:
return fileName.snakeCased
}
}

private func makeResource(
for node: ImageRenderedNode,
setNode: ImageComponentSetRenderedNode,
groupByFrame: Bool,
format: ImageFormat,
namingStyle: ImageNamingStyle,
folderPath: Path
) -> ImageResource {
let fileName = setNode.isSingleComponent
? node.base.name.camelized
: "\(setNode.name) \(node.base.name)".camelized

let fileName = resolveFileName(for: node, setNode: setNode, namingStyle: namingStyle)
let folderPath = resolveFolderPath(groupByFrame: groupByFrame, setNode: setNode, folderPath: folderPath)
let fileExtension = format.fileExtension

Expand All @@ -46,6 +60,7 @@ final class DefaultImageResourcesProvider: ImageResourcesProvider, ImagesFolderP
for nodes: [ImageComponentSetRenderedNode],
groupByFrame: Bool,
format: ImageFormat,
namingStyle: ImageNamingStyle,
folderPath: Path
) -> [ImageRenderedNode: ImageResource] {
var resources: [ImageRenderedNode: ImageResource] = [:]
Expand All @@ -57,6 +72,7 @@ final class DefaultImageResourcesProvider: ImageResourcesProvider, ImagesFolderP
setNode: setNode,
groupByFrame: groupByFrame,
format: format,
namingStyle: namingStyle,
folderPath: folderPath
)
}
Expand Down Expand Up @@ -108,13 +124,15 @@ final class DefaultImageResourcesProvider: ImageResourcesProvider, ImagesFolderP
groupByFrame: Bool,
format: ImageFormat,
postProcessor: String?,
namingStyle: ImageNamingStyle,
in folderPath: String
) -> Promise<[ImageRenderedNode: ImageResource]> {
perform(on: DispatchQueue.global(qos: .userInitiated)) {
self.makeResources(
for: nodes,
groupByFrame: groupByFrame,
format: format,
namingStyle: namingStyle,
folderPath: Path(folderPath)
)
}.nest { resources in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Foundation
import PathKit

final class ImageResourcesPostProcessor {

Expand All @@ -25,6 +26,9 @@ final class ImageResourcesPostProcessor {
// MARK: -

func execute(postProcessorPath: String, filePath: String) throws {
let postProcessorPath = Path(postProcessorPath).absolute()
let filePath = Path(filePath).absolute()

try shell("\(postProcessorPath) --filePath \(filePath)")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ protocol ImageResourcesProvider {
groupByFrame: Bool,
format: ImageFormat,
postProcessor: String?,
namingStyle: ImageNamingStyle,
in folderPath: String
) -> Promise<[ImageRenderedNode: ImageResource]>
}
7 changes: 7 additions & 0 deletions Sources/FigmaGenTools/Extensions/String+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ extension String {
.joined()
}

public var snakeCased: String {
components(separatedBy: CharacterSet.alphanumerics.inverted)
.filter { !$0.isEmpty }
.map { $0.lowercased() }
.joined(separator: "_")
}

// MARK: - Instance Methods

public func slice(
Expand Down

0 comments on commit 0f93e5b

Please sign in to comment.