Compare commits

..

No commits in common. "09556ba6e0737c427cb34bf3b190841de425f7b4" and "d4afa9c9e97f8937eb49f61024b1af7251ab747a" have entirely different histories.

8 changed files with 72 additions and 252 deletions

2
Jenkinsfile vendored
View File

@ -1,6 +1,6 @@
library "openiumpipeline" library "openiumpipeline"
env.DEVELOPER_DIR="/Applications/Xcode-15.4.0.app/Contents/Developer" env.DEVELOPER_DIR="/Applications/Xcode-15.3.0.app/Contents/Developer"
//env.SIMULATOR_DEVICE_TYPES="iPad--7th-generation-" //env.SIMULATOR_DEVICE_TYPES="iPad--7th-generation-"
env.IS_PACKAGE_SWIFT=1 env.IS_PACKAGE_SWIFT=1
env.TARGETS_MACOS=1 env.TARGETS_MACOS=1

View File

@ -225,7 +225,6 @@ swift run -c release ResgenSwift images $FORCE_FLAG "./Images/images.txt" \
6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppImage+GreatApp.swift`) 6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppImage+GreatApp.swift`)
7. `--static-members` *(optional)*: generate static properties or not 7. `--static-members` *(optional)*: generate static properties or not
> ⚠️ Svg images will be copied in the assets and rendered as "Original", however if those images are not rendered correctly you can force the png generation by adding the key word "png" like this: id arrow_back 15 ? png
## All at once ## All at once

View File

@ -8,13 +8,10 @@
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
@ -63,20 +60,13 @@ class XcassetsGenerator {
generatedAssetsPaths.append(imagesetName) generatedAssetsPaths.append(imagesetName)
// Generate output images path // Generate output images path
let output1x = "\(imagesetPath)/\(parsedImage.name).\(OutputImageExtension.png.rawValue)" let output1x = "\(imagesetPath)/\(parsedImage.name).\(XcassetsGenerator.outputImageExtension)"
let output2x = "\(imagesetPath)/\(parsedImage.name)@2x.\(OutputImageExtension.png.rawValue)" let output2x = "\(imagesetPath)/\(parsedImage.name)@2x.\(XcassetsGenerator.outputImageExtension)"
let output3x = "\(imagesetPath)/\(parsedImage.name)@3x.\(OutputImageExtension.png.rawValue)" let output3x = "\(imagesetPath)/\(parsedImage.name)@3x.\(XcassetsGenerator.outputImageExtension)"
// Check if we need to convert image // Check if we need to convert image
guard self.shouldGenerate(inputImagePath: imageData.path, xcassetImagePath: output1x) else {
var needToGenerateForSvg = false //print("\(parsedImage.name) -> Not regenerating")
if imageData.ext == "svg" && !parsedImage.imageExtensions.contains(.png) {
needToGenerateForSvg = true
}
guard self.shouldGenerate(inputImagePath: imageData.path, xcassetImagePath: output1x, needToGenerateForSvg: needToGenerateForSvg) else {
print("\(parsedImage.name) -> Not regenerating")
return return
} }
@ -90,55 +80,29 @@ class XcassetsGenerator {
print(error.description) print(error.description)
Images.exit(withError: error) Images.exit(withError: error)
} }
} else {
do {
let documentsDirectory = try fileManager.contentsOfDirectory(atPath: imagesetPath)
for filePath in documentsDirectory {
try fileManager.removeItem(atPath: "\(imagesetPath)/\(filePath)")
}
} catch {
print("Error deleting previous assets")
}
} }
// Convert image
let convertArguments = parsedImage.convertArguments let convertArguments = parsedImage.convertArguments
if imageData.ext == "svg" { if imageData.ext == "svg" {
if parsedImage.imageExtensions.contains(.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 -h 300 -o path/to/output.png
var command1x = ["\(svgConverter)", "\(imageData.path)"]
var command2x = ["\(svgConverter)", "\(imageData.path)"]
var command3x = ["\(svgConverter)", "\(imageData.path)"]
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -h 300 -o path/to/output.png self.addConvertArgument(command: &command1x, convertArgument: convertArguments.x1)
// /usr/local/bin/rsvg-convert path/to/image.png -w 200 -o path/to/output.png self.addConvertArgument(command: &command2x, convertArgument: convertArguments.x2)
// /usr/local/bin/rsvg-convert path/to/image.png -h 300 -o path/to/output.png self.addConvertArgument(command: &command3x, convertArgument: convertArguments.x3)
var command1x = ["\(svgConverter)", "\(imageData.path)"]
var command2x = ["\(svgConverter)", "\(imageData.path)"]
var command3x = ["\(svgConverter)", "\(imageData.path)"]
self.addConvertArgument(command: &command1x, convertArgument: convertArguments.x1) command1x.append(contentsOf: ["-o", output1x])
self.addConvertArgument(command: &command2x, convertArgument: convertArguments.x2) command2x.append(contentsOf: ["-o", output2x])
self.addConvertArgument(command: &command3x, convertArgument: convertArguments.x3) command3x.append(contentsOf: ["-o", output3x])
command1x.append(contentsOf: ["-o", output1x]) Shell.shell(command1x)
command2x.append(contentsOf: ["-o", output2x]) Shell.shell(command2x)
command3x.append(contentsOf: ["-o", output3x]) Shell.shell(command3x)
Shell.shell(command1x)
Shell.shell(command2x)
Shell.shell(command3x)
} else {
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 { } else {
// convert path/to/image.png -resize 200x300 path/to/output.png // convert path/to/image.png -resize 200x300 path/to/output.png
// convert path/to/image.png -resize 200x path/to/output.png // convert path/to/image.png -resize 200x path/to/output.png
@ -155,7 +119,7 @@ class XcassetsGenerator {
} }
// Write Content.json // Write Content.json
guard let imagesetContentJson = parsedImage.generateContentJson(isVector: imageData.ext == "svg") else { return } guard let imagesetContentJson = parsedImage.contentJson else { return }
let contentJsonFilePath = "\(imagesetPath)/Contents.json" let contentJsonFilePath = "\(imagesetPath)/Contents.json"
let contentJsonFilePathURL = URL(fileURLWithPath: contentJsonFilePath) let contentJsonFilePathURL = URL(fileURLWithPath: contentJsonFilePath)
@ -197,8 +161,8 @@ class XcassetsGenerator {
// MARK: - Helpers: bypass generation // MARK: - Helpers: bypass generation
private func shouldGenerate(inputImagePath: String, xcassetImagePath: String, needToGenerateForSvg: Bool) -> Bool { private func shouldGenerate(inputImagePath: String, xcassetImagePath: String) -> Bool {
if forceGeneration || needToGenerateForSvg { if forceGeneration {
return true return true
} }

View File

@ -7,30 +7,14 @@
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.filename < $1.filename }) let lhsImages = lhs.images.sorted(by: { $0.scale < $1.scale })
let rhsImages = rhs.images.sorted(by: { $0.filename < $1.filename }) let rhsImages = rhs.images.sorted(by: { $0.scale < $1.scale })
return lhsImages == rhsImages return lhsImages == rhsImages
} }
@ -38,39 +22,11 @@ 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"
}
}

View File

@ -7,30 +7,11 @@
import Foundation import Foundation
enum ImageExtension: String {
case png
}
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
@ -61,12 +42,10 @@ struct ParsedImage {
// MARK: - Assets // MARK: - Assets
func generateContentJson(isVector: Bool) -> String? { var contentJson: String? {
let encoder = JSONEncoder() let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted encoder.outputFormatting = .prettyPrinted
let imageContent = generateImageContent(isVector: isVector)
guard let data = try? encoder.encode(imageContent) else { guard let data = try? encoder.encode(imageContent) else {
let error = ImagesError.writeFile("Contents.json", "Error encoding json file") let error = ImagesError.writeFile("Contents.json", "Error encoding json file")
print(error.description) print(error.description)
@ -76,52 +55,30 @@ struct ParsedImage {
return String(data: data, encoding: .utf8) return String(data: data, encoding: .utf8)
} }
func generateImageContent(isVector: Bool) -> AssetContent { var imageContent: AssetContent {
return AssetContent(
if !imageExtensions.contains(.png) && isVector { images: [
//Generate svg AssetImageDescription(
return AssetContent( idiom: "universal",
images: [ scale: "1x",
AssetImageDescription( filename: "\(name).\(XcassetsGenerator.outputImageExtension)"
idiom: "universal",
filename: "\(name).\(OutputImageExtension.svg.rawValue)"
)
],
info: AssetInfo(
version: 1,
author: "ResgenSwift-Imagium"
), ),
properties: AssetProperties( AssetImageDescription(
preservesVectorRepresentation: true, idiom: "universal",
templateRenderingIntent: .original scale: "2x",
filename: "\(name)@2x.\(XcassetsGenerator.outputImageExtension)"
),
AssetImageDescription(
idiom: "universal",
scale: "3x",
filename: "\(name)@3x.\(XcassetsGenerator.outputImageExtension)"
) )
],
info: AssetInfo(
version: 1,
author: "ResgenSwift-Imagium"
) )
} else { )
//Generate png
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

View File

@ -39,20 +39,10 @@ class ImageFileParser {
return Int(splittedLine[3])! return Int(splittedLine[3])!
}() }()
var imageExtensions: [ImageExtension] = [] let image = ParsedImage(name: String(splittedLine[1]), tags: String(splittedLine[0]), width: width, height: height)
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)
} }

View File

@ -17,8 +17,8 @@ class ImageFileParserTests: XCTestCase {
# #
# SMAAS Support # SMAAS Support
# #
id image_one 25 ? png id image_one 25 ?
di image_two ? 50 webp png di image_two ? 50
d image_three 25 ? d image_three 25 ?
d image_four 75 ? d image_four 75 ?
""" """
@ -38,7 +38,6 @@ 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, [.png])
let secondImage = parsedImages.first { let secondImage = parsedImages.first {
$0.name == "image_two" $0.name == "image_two"
@ -47,6 +46,5 @@ class ImageFileParserTests: XCTestCase {
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, [.png])
} }
} }

View File

@ -127,7 +127,7 @@ final class ParsedImageTests: XCTestCase {
height: 10) height: 10)
// When // When
let property = parsedImage.generateImageContent(isVector: false) let property = parsedImage.imageContent
// Expect // Expect
let expect = AssetContent( let expect = AssetContent(
@ -135,17 +135,17 @@ final class ParsedImageTests: XCTestCase {
AssetImageDescription( AssetImageDescription(
idiom: "universal", idiom: "universal",
scale: "1x", scale: "1x",
filename: "\(parsedImage.name).\(OutputImageExtension.png.rawValue)" filename: "\(parsedImage.name).\(XcassetsGenerator.outputImageExtension)"
), ),
AssetImageDescription( AssetImageDescription(
idiom: "universal", idiom: "universal",
scale: "2x", scale: "2x",
filename: "\(parsedImage.name)@2x.\(OutputImageExtension.png.rawValue)" filename: "\(parsedImage.name)@2x.\(XcassetsGenerator.outputImageExtension)"
), ),
AssetImageDescription( AssetImageDescription(
idiom: "universal", idiom: "universal",
scale: "3x", scale: "3x",
filename: "\(parsedImage.name)@3x.\(OutputImageExtension.png.rawValue)" filename: "\(parsedImage.name)@3x.\(XcassetsGenerator.outputImageExtension)"
) )
], ],
info: AssetInfo( info: AssetInfo(
@ -156,48 +156,4 @@ final class ParsedImageTests: XCTestCase {
XCTAssertEqual(property, expect) XCTAssertEqual(property, expect)
} }
func testAssetPng() {
// Given
let imageName = "the_name"
let parsedImage = ParsedImage(name: imageName,
tags: "id",
width: 10,
height: 10,
imageExtensions: [.png])
// When
let property = parsedImage.generateImageContent(isVector: false)
// Expect
let expect = AssetContent(
images: [
AssetImageDescription(
idiom: "universal",
scale: "1x",
filename: "\(parsedImage.name).\(OutputImageExtension.png.rawValue)"
),
AssetImageDescription(
idiom: "universal",
scale: "2x",
filename: "\(parsedImage.name)@2x.\(OutputImageExtension.png.rawValue)"
),
AssetImageDescription(
idiom: "universal",
scale: "3x",
filename: "\(parsedImage.name)@3x.\(OutputImageExtension.png.rawValue)"
)
],
info: AssetInfo(
version: 1,
author: "ResgenSwift-Imagium"
)
)
debugPrint(property)
debugPrint(expect)
XCTAssertEqual(property, expect)
}
} }