Skip to content

Commit

Permalink
Add ability to configure frames names
Browse files Browse the repository at this point in the history
Closes #29
  • Loading branch information
subdan committed Sep 22, 2020
1 parent 40ab107 commit aeb9b03
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 38 deletions.
4 changes: 4 additions & 0 deletions CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ common:
# RegExp pattern for color name validation before exporting
nameValidateRegexp: '^[a-zA-Z_]+$' # RegExp pattern for: background, background_primary, widget_primary_background
icons:
# Name of the Figma's frame where icons components are located
figmaFrameName: Colors
# RegExp pattern for icon name validation before exporting
nameValidateRegexp: '^(ic)_(\d\d)_([a-z0-9_]+)$' # RegExp pattern for: ic_24_icon_name, ic_24_icon
images:
# Name of the Figma's frame where image components are located
figmaFrameName: Illustrations
# RegExp pattern for image name validation before exporting
nameValidateRegexp: '^(img)_([a-z0-9_]+)$' # RegExp pattern for: img_image_name

Expand Down
9 changes: 9 additions & 0 deletions Examples/AndroidExample/figma-export.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ figma:
lightFileId: BEjfU0kCVnPqXdRLfoLvkf
darkFileId: QwF30YrucxVwQyBNT0C09i

# [optional] Common export parameters
common:
icons:
# Name of the Figma's frame where icons components are located
figmaFrameName: Colors
images:
# Name of the Figma's frame where image components are located
figmaFrameName: Illustrations

android:
mainRes: ./app/src/main/res
images:
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,11 +311,12 @@ File | Styles

For `figma-export icons`

Your Figma file must contains a frame with `Icons` name which contains components for each icon.
By default your Figma file should contains a frame with `Icons` name which contains components for each icon. You may change a frame name in a [config](Config.md) file by setting `common.icons.figmaFrameName` property.

For `figma-export images`

Your Figma file must contains a frame with `Illustrations` name which contains components for each illustration.
Your Figma file should contains a frame with `Illustrations` name which contains components for each illustration. You may change a frame name in a [config](Config.md) file by setting `common.images.figmaFrameName` property.

If you support dark mode you must have two Figma files.

For `figma-export typography`.
Expand Down
39 changes: 31 additions & 8 deletions Release/figma-export.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
figma:
# Identifier of Figma file
# Identifier of the file containing light color palette, icons and light images. To obtain a file id, open the file in the browser. The file id will be present in the URL after the word file and before the file name.
lightFileId: shPilWnVdJfo10YF12345
# [optional] Identifier of Figma file for dark mode
# [optional] Identifier of the file containing dark color palette and dark images.
darkFileId: KfF6DnJTWHGZzC912345

# [optional] Common export parameters
Expand All @@ -11,24 +11,30 @@ common:
# RegExp pattern for color name validation before exporting
nameValidateRegexp: '^[a-zA-Z_]+$' # RegExp pattern for: background, background_primary, widget_primary_background
icons:
# Name of the Figma's frame where icons components are located
figmaFrameName: Colors
# RegExp pattern for icon name validation before exporting
nameValidateRegexp: '^(ic)_(\d\d)_([a-z0-9_]+)$' # RegExp pattern for: ic_24_icon_name, ic_24_icon
images:
# Name of the Figma's frame where image components are located
figmaFrameName: Illustrations
# RegExp pattern for image name validation before exporting
nameValidateRegexp: '^(img)_([a-z0-9_]+)$' # RegExp pattern for: img_image_name

# [optional] iOS export parameters
ios:
# Path to xcodeproj
xcodeprojPath: "./Example.xcodeproj"
# Xcode Target containing resources and corresponding swift code
target: "UIComponents"
# Absolute or relative path to the Assets.xcassets directory
xcassetsPath: "./Resources/Assets.xcassets"
# Is Assets.xcassets located in the main bundle?
xcassetsInMainBundle: true

# Parameters for exporting colors
colors:
# Should be generate color assets instead of pure swift code
# How to export colors? Use .xcassets and UIColor extension (useColorAssets = true) or extension only (useColorAssets = false)
useColorAssets: True
# [required if useColorAssets: True] Name of the folder inside Assets.xcassets where to place colors (.colorset directories)
assetsFolder: Colors
Expand All @@ -47,13 +53,15 @@ ios:
assetsFolder: Icons
# Icon name style: camelCase or snake_case
nameStyle: camelCase
# [optional] Enable Preserve Vector Data for specified icons
# [optional] An array of icon names that will supports Preseve Vecotor Data
preservesVectorRepresentation:
- ic24TabBarMain
- ic24TabBarEvents
- ic24TabBarProfile
# [optional] Absolute or relative path to swift file where to export icons (SwiftUI’s Image) for accessing from the code (e.g. Image.illZeroNoInternet)
swiftUIImageSwift: "./Source/Image+extension_icons.swift"
# [optional] Absolute or relative path to swift file where to generate extension for UIImage for accessing icons from the code (e.g. UIImage.ic24ArrowRight)
imageSwift: "./Example/Source/UIImage+extension_icons.swift"

# Parameters for exporting images
images:
Expand All @@ -63,16 +71,31 @@ ios:
nameStyle: camelCase
# [optional] Absolute or relative path to swift file where to export images (SwiftUI’s Image) for accessing from the code (e.g. Image.illZeroNoInternet)
swiftUIImageSwift: "./Source/Image+extension_illustrations.swift"
# [optional] Absolute or relative path to swift file where to generate extension for UIImage for accessing illustrations from the code (e.g. UIImage.illZeroNoInternet)
imageSwift: "./Example/Source/UIImage+extension_illustrations.swift"

# Parameters for exporting typography
typography:
# Path to directory where to place UIFont+extension.swift file
fontExtensionDirectory: "./Source/UIComponents/"
# Will FigmaExport generate UILabel for each text style (font) e.g. HeaderLabel, BodyLabel, CaptionLabel.
# [optional] Absolute or relative path to swift file where to export UIKit fonts (UIFont extension).
fontSwift: "./Source/UIComponents/UIFont+extension.swift"
# [optional] Absolute or relative path to swift file where to export SwiftUI fonts (Font extension).
swiftUIFontSwift: "./Source/View/Common/Font+extension.swift"
# Should FigmaExport generate UILabel for each text style (font)? E.g. HeaderLabel, BodyLabel, CaptionLabel
generateLabels: true
# Path to directory where to place UILabel for each text style (font) (Requred if generateLabels = true)
# Relative or absolute path to directory where to place UILabel for each text style (font) (Requred if generateLabels = true)
labelsDirectory: "./Source/UIComponents/"

# [optional] Android export parameters
android:
# Relative or absolute path to the `main/res` folder including it. The colors/icons/imags will be exported to this folder
mainRes: "./main/res"
# Parameters for exporting images
images:
# Image file format: svg or png
format: webp
# Format options for webp format only
webpOptions:
# Encoding type: lossy or lossless
encoding: lossy
# Encoding quality in percents. Only for lossy encoding.
quality: 90
6 changes: 0 additions & 6 deletions Sources/FigmaAPI/Endpoint/ComponentsEndpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,3 @@ public struct ContainingFrame: Codable {
public let name: String?
public let pageName: String
}

public enum FrameName: String, Codable {
case components = "Components"
case icons = "Icons"
case illustrations = "Illustrations"
}
14 changes: 8 additions & 6 deletions Sources/FigmaExport/Input/Params.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ struct Params: Decodable {

struct Common: Decodable {
struct Colors: Decodable {
let nameValidateRegexp: String
let nameValidateRegexp: String?
}

struct Icons: Decodable {
let nameValidateRegexp: String
let nameValidateRegexp: String?
let figmaFrameName: String?
}

struct Images: Decodable {
let nameValidateRegexp: String
let nameValidateRegexp: String?
let figmaFrameName: String?
}

let colors: Colors
let icons: Icons
let images: Images
let colors: Colors?
let icons: Icons?
let images: Images?
}

enum NameStyle: String, Decodable {
Expand Down
28 changes: 18 additions & 10 deletions Sources/FigmaExport/Loaders/ImagesLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ final class ImagesLoader {
let params: Params
let platform: Platform

private var iconsFrameName: String {
params.common?.icons?.figmaFrameName ?? "Icons"
}

private var imagesFrameName: String {
params.common?.images?.figmaFrameName ?? "Illustrations"
}

init(figmaClient: FigmaClient, params: Params, platform: Platform) {
self.figmaClient = figmaClient
self.params = params
Expand All @@ -20,14 +28,14 @@ final class ImagesLoader {
(.ios, .svg):
return try _loadImages(
fileId: params.figma.lightFileId,
frameName: .icons,
frameName: iconsFrameName,
params: SVGParams(),
filter: filter
).map { ImagePack.singleScale($0) }
case (.ios, _):
return try _loadImages(
fileId: params.figma.lightFileId,
frameName: .icons,
frameName: iconsFrameName,
params: PDFParams(),
filter: filter
).map { ImagePack.singleScale($0) }
Expand All @@ -39,13 +47,13 @@ final class ImagesLoader {
case (.android, .png), (.android, .webp), (.ios, .none):
let lightImages = try loadPNGImages(
fileId: params.figma.lightFileId,
frameName: .illustrations,
frameName: imagesFrameName,
filter: filter,
platform: platform)
let darkImages = try params.figma.darkFileId.map {
try loadPNGImages(
fileId: $0,
frameName: .illustrations,
frameName: imagesFrameName,
filter: filter,
platform: platform)
}
Expand All @@ -56,14 +64,14 @@ final class ImagesLoader {
default:
let light = try _loadImages(
fileId: params.figma.lightFileId,
frameName: .illustrations,
frameName: imagesFrameName,
params: SVGParams(),
filter: filter)

let dark = try params.figma.darkFileId.map {
try _loadImages(
fileId: $0,
frameName: .illustrations,
frameName: imagesFrameName,
params: SVGParams(),
filter: filter)
}
Expand All @@ -76,10 +84,10 @@ final class ImagesLoader {

// MARK: - Helpers

private func fetchImageComponents(fileId: String, frameName: FrameName, filter: String? = nil) throws -> [NodeId: Component] {
private func fetchImageComponents(fileId: String, frameName: String, filter: String? = nil) throws -> [NodeId: Component] {
var components = try loadComponents(fileId: fileId)
.filter {
$0.containingFrame.name == frameName.rawValue &&
$0.containingFrame.name == frameName &&
($0.description == platform.rawValue || $0.description == nil || $0.description == "") &&
$0.description?.contains("none") == false
}
Expand All @@ -94,7 +102,7 @@ final class ImagesLoader {
return Dictionary(uniqueKeysWithValues: components.map { ($0.nodeId, $0) })
}

private func _loadImages(fileId: String, frameName: FrameName, params: FormatParams, filter: String? = nil) throws -> [Image] {
private func _loadImages(fileId: String, frameName: String, params: FormatParams, filter: String? = nil) throws -> [Image] {
let imagesDict = try fetchImageComponents(fileId: fileId, frameName: frameName, filter: filter)

guard !imagesDict.isEmpty else {
Expand All @@ -114,7 +122,7 @@ final class ImagesLoader {
}
}

private func loadPNGImages(fileId: String, frameName: FrameName, filter: String? = nil, platform: Platform) throws -> [ImagePack] {
private func loadPNGImages(fileId: String, frameName: String, filter: String? = nil, platform: Platform) throws -> [ImagePack] {
let imagesDict = try fetchImageComponents(fileId: fileId, frameName: frameName, filter: filter)

guard !imagesDict.isEmpty else {
Expand Down
4 changes: 2 additions & 2 deletions Sources/FigmaExport/Subcommands/ExportColors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ extension FigmaExportCommand {
logger.info("Processing colors...")
let processor = ColorsProcessor(
platform: .ios,
nameValidateRegexp: params.common?.colors.nameValidateRegexp,
nameValidateRegexp: params.common?.colors?.nameValidateRegexp,
nameStyle: params.ios?.colors.nameStyle
)
let colorPairs = try processor.process(light: colors.light, dark: colors.dark).get()
Expand All @@ -54,7 +54,7 @@ extension FigmaExportCommand {
logger.info("Processing colors...")
let processor = ColorsProcessor(
platform: .android,
nameValidateRegexp: params.common?.colors.nameValidateRegexp,
nameValidateRegexp: params.common?.colors?.nameValidateRegexp,
nameStyle: .snakeCase
)
let colorPairs = try processor.process(light: colors.light, dark: colors.dark).get()
Expand Down
4 changes: 2 additions & 2 deletions Sources/FigmaExport/Subcommands/ExportIcons.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extension FigmaExportCommand {
logger.info("Processing icons...")
let processor = ImagesProcessor(
platform: .ios,
nameValidateRegexp: params.common?.icons.nameValidateRegexp,
nameValidateRegexp: params.common?.icons?.nameValidateRegexp,
nameStyle: params.ios?.icons.nameStyle
)
let icons = try processor.process(assets: images).get()
Expand Down Expand Up @@ -105,7 +105,7 @@ extension FigmaExportCommand {
logger.info("Processing icons...")
let processor = ImagesProcessor(
platform: .android,
nameValidateRegexp: params.common?.icons.nameValidateRegexp,
nameValidateRegexp: params.common?.icons?.nameValidateRegexp,
nameStyle: .snakeCase
)
let icons = try processor.process(light: images, dark: nil).get()
Expand Down
4 changes: 2 additions & 2 deletions Sources/FigmaExport/Subcommands/ExportImages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extension FigmaExportCommand {
logger.info("Processing images...")
let processor = ImagesProcessor(
platform: .ios,
nameValidateRegexp: params.common?.images.nameValidateRegexp,
nameValidateRegexp: params.common?.images?.nameValidateRegexp,
nameStyle: params.ios?.images.nameStyle
)
let images = try processor.process(light: imagesTuple.light, dark: imagesTuple.dark).get()
Expand Down Expand Up @@ -102,7 +102,7 @@ extension FigmaExportCommand {
logger.info("Processing images...")
let processor = ImagesProcessor(
platform: .android,
nameValidateRegexp: params.common?.images.nameValidateRegexp,
nameValidateRegexp: params.common?.images?.nameValidateRegexp,
nameStyle: .snakeCase
)
let images = try processor.process(light: imagesTuple.light, dark: imagesTuple.dark).get()
Expand Down

0 comments on commit aeb9b03

Please sign in to comment.