DEVTOOLS-186 Exporter les images de resgen en svg #12
@ -8,10 +8,13 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import ToolCore
|
import ToolCore
|
||||||
|
|
||||||
|
enum OutputImageExtension: String {
|
||||||
|
case png
|
||||||
|
case svg
|
||||||
|
}
|
||||||
|
|
||||||
class XcassetsGenerator {
|
class XcassetsGenerator {
|
||||||
|
|
||||||
static let outputImageExtension = "png"
|
|
||||||
|
|
||||||
let forceGeneration: Bool
|
let forceGeneration: Bool
|
||||||
|
|
||||||
// MARK: - Init
|
// MARK: - Init
|
||||||
@ -60,10 +63,10 @@ class XcassetsGenerator {
|
|||||||
generatedAssetsPaths.append(imagesetName)
|
generatedAssetsPaths.append(imagesetName)
|
||||||
|
|
||||||
// Generate output images path
|
// Generate output images path
|
||||||
let output1x = "\(imagesetPath)/\(parsedImage.name).\(XcassetsGenerator.outputImageExtension)"
|
let output1x = "\(imagesetPath)/\(parsedImage.name).\(OutputImageExtension.png.rawValue)"
|
||||||
let output2x = "\(imagesetPath)/\(parsedImage.name)@2x.\(XcassetsGenerator.outputImageExtension)"
|
let output2x = "\(imagesetPath)/\(parsedImage.name)@2x.\(OutputImageExtension.png.rawValue)"
|
||||||
let output3x = "\(imagesetPath)/\(parsedImage.name)@3x.\(XcassetsGenerator.outputImageExtension)"
|
let output3x = "\(imagesetPath)/\(parsedImage.name)@3x.\(OutputImageExtension.png.rawValue)"
|
||||||
|
|
||||||
// Check if we need to convert image
|
// Check if we need to convert image
|
||||||
guard self.shouldGenerate(inputImagePath: imageData.path, xcassetImagePath: output1x) else {
|
guard self.shouldGenerate(inputImagePath: imageData.path, xcassetImagePath: output1x) else {
|
||||||
//print("\(parsedImage.name) -> Not regenerating")
|
//print("\(parsedImage.name) -> Not regenerating")
|
||||||
@ -81,25 +84,38 @@ class XcassetsGenerator {
|
|||||||
Images.exit(withError: error)
|
Images.exit(withError: error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert image
|
|
||||||
let convertArguments = parsedImage.convertArguments
|
let convertArguments = parsedImage.convertArguments
|
||||||
if imageData.ext == "svg" {
|
|
||||||
|
if parsedImage.imageExtensions.contains(.vector) {
|
||||||
|
let output = "\(imagesetPath)/\(parsedImage.name).\(OutputImageExtension.svg.rawValue)"
|
||||||
|
let tempURL = URL(fileURLWithPath: output)
|
||||||
|
|
||||||
|
do {
|
||||||
|
if FileManager.default.fileExists(atPath: tempURL.path) {
|
||||||
|
try FileManager.default.removeItem(atPath: tempURL.path)
|
||||||
|
}
|
||||||
|
try FileManager.default.copyItem(atPath: imageData.path, toPath: tempURL.path)
|
||||||
|
} catch {
|
||||||
|
print(error.localizedDescription)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if imageData.ext == "svg" {
|
||||||
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -h 300 -o path/to/output.png
|
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -h 300 -o path/to/output.png
|
||||||
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -o path/to/output.png
|
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -o path/to/output.png
|
||||||
// /usr/local/bin/rsvg-convert path/to/image.png -h 300 -o path/to/output.png
|
// /usr/local/bin/rsvg-convert path/to/image.png -h 300 -o path/to/output.png
|
||||||
var command1x = ["\(svgConverter)", "\(imageData.path)"]
|
var command1x = ["\(svgConverter)", "\(imageData.path)"]
|
||||||
var command2x = ["\(svgConverter)", "\(imageData.path)"]
|
var command2x = ["\(svgConverter)", "\(imageData.path)"]
|
||||||
var command3x = ["\(svgConverter)", "\(imageData.path)"]
|
var command3x = ["\(svgConverter)", "\(imageData.path)"]
|
||||||
|
|
||||||
self.addConvertArgument(command: &command1x, convertArgument: convertArguments.x1)
|
self.addConvertArgument(command: &command1x, convertArgument: convertArguments.x1)
|
||||||
self.addConvertArgument(command: &command2x, convertArgument: convertArguments.x2)
|
self.addConvertArgument(command: &command2x, convertArgument: convertArguments.x2)
|
||||||
self.addConvertArgument(command: &command3x, convertArgument: convertArguments.x3)
|
self.addConvertArgument(command: &command3x, convertArgument: convertArguments.x3)
|
||||||
|
|
||||||
command1x.append(contentsOf: ["-o", output1x])
|
command1x.append(contentsOf: ["-o", output1x])
|
||||||
command2x.append(contentsOf: ["-o", output2x])
|
command2x.append(contentsOf: ["-o", output2x])
|
||||||
command3x.append(contentsOf: ["-o", output3x])
|
command3x.append(contentsOf: ["-o", output3x])
|
||||||
|
|
||||||
Shell.shell(command1x)
|
Shell.shell(command1x)
|
||||||
Shell.shell(command2x)
|
Shell.shell(command2x)
|
||||||
Shell.shell(command3x)
|
Shell.shell(command3x)
|
||||||
|
@ -7,14 +7,30 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
enum TemplateRenderingIntent: String, Codable {
|
||||||
|
case template
|
||||||
|
case original
|
||||||
|
}
|
||||||
|
|
||||||
struct AssetContent: Codable, Equatable {
|
struct AssetContent: Codable, Equatable {
|
||||||
let images: [AssetImageDescription]
|
let images: [AssetImageDescription]
|
||||||
let info: AssetInfo
|
let info: AssetInfo
|
||||||
|
let properties: AssetProperties?
|
||||||
|
|
||||||
|
init(
|
||||||
|
images: [AssetImageDescription],
|
||||||
|
info: AssetInfo,
|
||||||
|
properties: AssetProperties? = nil
|
||||||
|
) {
|
||||||
|
self.images = images
|
||||||
|
self.info = info
|
||||||
|
self.properties = properties
|
||||||
|
}
|
||||||
|
|
||||||
static func == (lhs: AssetContent, rhs: AssetContent) -> Bool {
|
static func == (lhs: AssetContent, rhs: AssetContent) -> Bool {
|
||||||
guard lhs.images.count == rhs.images.count else { return false }
|
guard lhs.images.count == rhs.images.count else { return false }
|
||||||
let lhsImages = lhs.images.sorted(by: { $0.scale < $1.scale })
|
let lhsImages = lhs.images.sorted(by: { $0.filename < $1.filename })
|
||||||
let rhsImages = rhs.images.sorted(by: { $0.scale < $1.scale })
|
let rhsImages = rhs.images.sorted(by: { $0.filename < $1.filename })
|
||||||
|
|
||||||
return lhsImages == rhsImages
|
return lhsImages == rhsImages
|
||||||
}
|
}
|
||||||
@ -22,11 +38,39 @@ struct AssetContent: Codable, Equatable {
|
|||||||
|
|
||||||
struct AssetImageDescription: Codable, Equatable {
|
struct AssetImageDescription: Codable, Equatable {
|
||||||
let idiom: String
|
let idiom: String
|
||||||
let scale: String
|
let scale: String?
|
||||||
let filename: String
|
let filename: String
|
||||||
|
|
||||||
|
init(
|
||||||
|
idiom: String,
|
||||||
|
scale: String? = nil,
|
||||||
|
filename: String
|
||||||
|
) {
|
||||||
|
self.idiom = idiom
|
||||||
|
self.scale = scale
|
||||||
|
self.filename = filename
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AssetInfo: Codable, Equatable {
|
struct AssetInfo: Codable, Equatable {
|
||||||
let version: Int
|
let version: Int
|
||||||
let author: String
|
let author: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AssetProperties: Codable, Equatable {
|
||||||
|
let preservesVectorRepresentation: Bool
|
||||||
|
let templateRenderingIntent: TemplateRenderingIntent?
|
||||||
|
|
||||||
|
init(
|
||||||
|
preservesVectorRepresentation: Bool,
|
||||||
|
templateRenderingIntent: TemplateRenderingIntent? = nil
|
||||||
|
) {
|
||||||
|
self.preservesVectorRepresentation = preservesVectorRepresentation
|
||||||
|
self.templateRenderingIntent = templateRenderingIntent
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case preservesVectorRepresentation = "preserves-vector-representation"
|
||||||
|
case templateRenderingIntent = "template-rendering-intent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,12 +7,31 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
enum ImageExtension: String {
|
||||||
|
case vector
|
||||||
|
}
|
||||||
|
|
||||||
struct ParsedImage {
|
struct ParsedImage {
|
||||||
let name: String
|
let name: String
|
||||||
let tags: String
|
let tags: String
|
||||||
let width: Int
|
let width: Int
|
||||||
let height: Int
|
let height: Int
|
||||||
|
let imageExtensions: [ImageExtension]
|
||||||
|
|
||||||
|
init(
|
||||||
|
name: String,
|
||||||
|
tags: String,
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
imageExtensions: [ImageExtension] = []
|
||||||
|
) {
|
||||||
|
self.name = name
|
||||||
|
self.tags = tags
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.imageExtensions = imageExtensions
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Convert
|
// MARK: - Convert
|
||||||
|
|
||||||
var convertArguments: (x1: ConvertArgument, x2: ConvertArgument, x3: ConvertArgument) {
|
var convertArguments: (x1: ConvertArgument, x2: ConvertArgument, x3: ConvertArgument) {
|
||||||
@ -56,29 +75,49 @@ struct ParsedImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var imageContent: AssetContent {
|
var imageContent: AssetContent {
|
||||||
return AssetContent(
|
if imageExtensions.contains(.vector) {
|
||||||
images: [
|
return AssetContent(
|
||||||
AssetImageDescription(
|
images: [
|
||||||
idiom: "universal",
|
AssetImageDescription(
|
||||||
scale: "1x",
|
idiom: "universal",
|
||||||
filename: "\(name).\(XcassetsGenerator.outputImageExtension)"
|
filename: "\(name).\(OutputImageExtension.svg.rawValue)"
|
||||||
|
)
|
||||||
|
],
|
||||||
|
info: AssetInfo(
|
||||||
|
version: 1,
|
||||||
|
author: "ResgenSwift-Imagium"
|
||||||
),
|
),
|
||||||
AssetImageDescription(
|
properties: AssetProperties(
|
||||||
idiom: "universal",
|
preservesVectorRepresentation: true,
|
||||||
scale: "2x",
|
templateRenderingIntent: .template
|
||||||
filename: "\(name)@2x.\(XcassetsGenerator.outputImageExtension)"
|
|
||||||
),
|
|
||||||
AssetImageDescription(
|
|
||||||
idiom: "universal",
|
|
||||||
scale: "3x",
|
|
||||||
filename: "\(name)@3x.\(XcassetsGenerator.outputImageExtension)"
|
|
||||||
)
|
)
|
||||||
],
|
|
||||||
info: AssetInfo(
|
|
||||||
version: 1,
|
|
||||||
author: "ResgenSwift-Imagium"
|
|
||||||
)
|
)
|
||||||
)
|
} else {
|
||||||
|
|
||||||
|
return AssetContent(
|
||||||
|
images: [
|
||||||
|
AssetImageDescription(
|
||||||
|
idiom: "universal",
|
||||||
|
scale: "1x",
|
||||||
|
filename: "\(name).\(OutputImageExtension.png.rawValue)"
|
||||||
|
),
|
||||||
|
AssetImageDescription(
|
||||||
|
idiom: "universal",
|
||||||
|
scale: "2x",
|
||||||
|
filename: "\(name)@2x.\(OutputImageExtension.png.rawValue)"
|
||||||
|
),
|
||||||
|
AssetImageDescription(
|
||||||
|
idiom: "universal",
|
||||||
|
scale: "3x",
|
||||||
|
filename: "\(name)@3x.\(OutputImageExtension.png.rawValue)"
|
||||||
|
)
|
||||||
|
],
|
||||||
|
info: AssetInfo(
|
||||||
|
version: 1,
|
||||||
|
author: "ResgenSwift-Imagium"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Extension property
|
// MARK: - Extension property
|
||||||
|
@ -38,11 +38,21 @@ class ImageFileParser {
|
|||||||
}
|
}
|
||||||
return Int(splittedLine[3])!
|
return Int(splittedLine[3])!
|
||||||
}()
|
}()
|
||||||
|
|
||||||
let image = ParsedImage(name: String(splittedLine[1]), tags: String(splittedLine[0]), width: width, height: height)
|
var imageExtensions: [ImageExtension] = []
|
||||||
|
|
||||||
|
splittedLine.forEach { stringExtension in
|
||||||
|
if let imageExtension = ImageExtension(rawValue: String(stringExtension)) {
|
||||||
|
imageExtensions.append(imageExtension)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let image = ParsedImage(name: String(splittedLine[1]), tags: String(splittedLine[0]), width: width, height: height, imageExtensions: imageExtensions)
|
||||||
imagesToGenerate.append(image)
|
imagesToGenerate.append(image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print(imagesToGenerate)
|
||||||
|
|
||||||
return imagesToGenerate.filter {
|
return imagesToGenerate.filter {
|
||||||
$0.tags.contains(platform.rawValue)
|
$0.tags.contains(platform.rawValue)
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ class ImageFileParserTests: XCTestCase {
|
|||||||
#
|
#
|
||||||
# SMAAS Support
|
# SMAAS Support
|
||||||
#
|
#
|
||||||
id image_one 25 ?
|
id image_one 25 ? vector
|
||||||
di image_two ? 50
|
di image_two ? 50 webp vector
|
||||||
d image_three 25 ?
|
d image_three 25 ?
|
||||||
d image_four 75 ?
|
d image_four 75 ?
|
||||||
"""
|
"""
|
||||||
@ -38,13 +38,15 @@ class ImageFileParserTests: XCTestCase {
|
|||||||
XCTAssertEqual(firstImage!.tags, "id")
|
XCTAssertEqual(firstImage!.tags, "id")
|
||||||
XCTAssertEqual(firstImage!.width, 25)
|
XCTAssertEqual(firstImage!.width, 25)
|
||||||
XCTAssertEqual(firstImage!.height, -1)
|
XCTAssertEqual(firstImage!.height, -1)
|
||||||
|
XCTAssertEqual(firstImage!.imageExtensions, [.vector])
|
||||||
|
|
||||||
let secondImage = parsedImages.first {
|
let secondImage = parsedImages.first {
|
||||||
$0.name == "image_two"
|
$0.name == "image_two"
|
||||||
}
|
}
|
||||||
XCTAssertEqual(secondImage!.name, "image_two")
|
XCTAssertEqual(secondImage!.name, "image_two")
|
||||||
XCTAssertEqual(secondImage!.tags, "di")
|
XCTAssertEqual(secondImage!.tags, "di")
|
||||||
XCTAssertEqual(secondImage!.width, -1)
|
XCTAssertEqual(secondImage!.width, -1)
|
||||||
XCTAssertEqual(secondImage!.height, 50)
|
XCTAssertEqual(secondImage!.height, 50)
|
||||||
|
XCTAssertEqual(firstImage!.imageExtensions, [.vector])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,17 +135,17 @@ final class ParsedImageTests: XCTestCase {
|
|||||||
AssetImageDescription(
|
AssetImageDescription(
|
||||||
idiom: "universal",
|
idiom: "universal",
|
||||||
scale: "1x",
|
scale: "1x",
|
||||||
filename: "\(parsedImage.name).\(XcassetsGenerator.outputImageExtension)"
|
filename: "\(parsedImage.name).\(OutputImageExtension.png.rawValue)"
|
||||||
),
|
),
|
||||||
AssetImageDescription(
|
AssetImageDescription(
|
||||||
idiom: "universal",
|
idiom: "universal",
|
||||||
scale: "2x",
|
scale: "2x",
|
||||||
filename: "\(parsedImage.name)@2x.\(XcassetsGenerator.outputImageExtension)"
|
filename: "\(parsedImage.name)@2x.\(OutputImageExtension.png.rawValue)"
|
||||||
),
|
),
|
||||||
AssetImageDescription(
|
AssetImageDescription(
|
||||||
idiom: "universal",
|
idiom: "universal",
|
||||||
scale: "3x",
|
scale: "3x",
|
||||||
filename: "\(parsedImage.name)@3x.\(XcassetsGenerator.outputImageExtension)"
|
filename: "\(parsedImage.name)@3x.\(OutputImageExtension.png.rawValue)"
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
info: AssetInfo(
|
info: AssetInfo(
|
||||||
@ -156,4 +156,40 @@ final class ParsedImageTests: XCTestCase {
|
|||||||
|
|
||||||
XCTAssertEqual(property, expect)
|
XCTAssertEqual(property, expect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAssetVector() {
|
||||||
|
// Given
|
||||||
|
let imageName = "the_name"
|
||||||
|
let parsedImage = ParsedImage(name: imageName,
|
||||||
|
tags: "id",
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
imageExtensions: [.vector])
|
||||||
|
|
||||||
|
// When
|
||||||
|
let property = parsedImage.imageContent
|
||||||
|
|
||||||
|
// Expect
|
||||||
|
let expect = AssetContent(
|
||||||
|
images: [
|
||||||
|
AssetImageDescription(
|
||||||
|
idiom: "universal",
|
||||||
|
filename: "\(parsedImage.name).\(OutputImageExtension.svg.rawValue)"
|
||||||
|
)
|
||||||
|
],
|
||||||
|
info: AssetInfo(
|
||||||
|
version: 1,
|
||||||
|
author: "ResgenSwift-Imagium"
|
||||||
|
),
|
||||||
|
properties: AssetProperties(
|
||||||
|
preservesVectorRepresentation: true,
|
||||||
|
templateRenderingIntent: .template
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
debugPrint(property)
|
||||||
|
debugPrint(expect)
|
||||||
|
|
||||||
|
XCTAssertEqual(property, expect)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user