Command line to generate R2Font
This commit is contained in:
parent
e159b2e752
commit
ce3cac90be
10
.gitignore
vendored
10
.gitignore
vendored
@ -218,6 +218,13 @@ DerivedData/
|
|||||||
!*.xcworkspace/contents.xcworkspacedata
|
!*.xcworkspace/contents.xcworkspacedata
|
||||||
/*.gcno
|
/*.gcno
|
||||||
|
|
||||||
|
/.build
|
||||||
|
/Packages
|
||||||
|
/*.xcodeproj
|
||||||
|
xcuserdata/
|
||||||
|
DerivedData/
|
||||||
|
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||||
|
|
||||||
### Xcode Patch ###
|
### Xcode Patch ###
|
||||||
**/xcshareddata/WorkspaceSettings.xcsettings
|
**/xcshareddata/WorkspaceSettings.xcsettings
|
||||||
|
|
||||||
@ -326,3 +333,6 @@ fabric.properties
|
|||||||
!/gradle/wrapper/gradle-wrapper.jar
|
!/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
# End of https://www.gitignore.io/api/macos,carthage,symfony,xcode,android,androidstudio
|
# End of https://www.gitignore.io/api/macos,carthage,symfony,xcode,android,androidstudio
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
16
Package.resolved
Normal file
16
Package.resolved
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"object": {
|
||||||
|
"pins": [
|
||||||
|
{
|
||||||
|
"package": "swift-argument-parser",
|
||||||
|
"repositoryURL": "https://github.com/apple/swift-argument-parser",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "e1465042f195f374b94f915ba8ca49de24300a0d",
|
||||||
|
"version": "1.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"version": 1
|
||||||
|
}
|
31
Package.swift
Normal file
31
Package.swift
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// swift-tools-version:5.3
|
||||||
|
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "ResgenSwift",
|
||||||
|
dependencies: [
|
||||||
|
// Dependencies declare other packages that this package depends on.
|
||||||
|
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0")
|
||||||
|
],
|
||||||
|
targets: [
|
||||||
|
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||||
|
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||||
|
.target(
|
||||||
|
name: "ResgenSwift",
|
||||||
|
dependencies: ["FontToolCore"]),
|
||||||
|
.target(
|
||||||
|
name: "FontToolCore",
|
||||||
|
dependencies: [
|
||||||
|
"CLIToolCore",
|
||||||
|
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||||
|
]),
|
||||||
|
// Helper targets
|
||||||
|
.target(name: "CLIToolCore"),
|
||||||
|
// Test targets
|
||||||
|
.testTarget(
|
||||||
|
name: "ResgenSwiftTests",
|
||||||
|
dependencies: ["ResgenSwift"]),
|
||||||
|
]
|
||||||
|
)
|
BIN
SampleFiles/Fonts/Lato/Lato-Black.ttf
Normal file
BIN
SampleFiles/Fonts/Lato/Lato-Black.ttf
Normal file
Binary file not shown.
BIN
SampleFiles/Fonts/Lato/Lato-BlackItalic.ttf
Normal file
BIN
SampleFiles/Fonts/Lato/Lato-BlackItalic.ttf
Normal file
Binary file not shown.
BIN
SampleFiles/Fonts/Lato/Lato-Bold.ttf
Normal file
BIN
SampleFiles/Fonts/Lato/Lato-Bold.ttf
Normal file
Binary file not shown.
BIN
SampleFiles/Fonts/Lato/Lato-BoldItalic.ttf
Normal file
BIN
SampleFiles/Fonts/Lato/Lato-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
SampleFiles/Fonts/Lato/Lato-Italic.ttf
Normal file
BIN
SampleFiles/Fonts/Lato/Lato-Italic.ttf
Normal file
Binary file not shown.
BIN
SampleFiles/Fonts/Lato/Lato-Light.ttf
Normal file
BIN
SampleFiles/Fonts/Lato/Lato-Light.ttf
Normal file
Binary file not shown.
BIN
SampleFiles/Fonts/Lato/Lato-LightItalic.ttf
Normal file
BIN
SampleFiles/Fonts/Lato/Lato-LightItalic.ttf
Normal file
Binary file not shown.
BIN
SampleFiles/Fonts/Lato/Lato-Regular.ttf
Normal file
BIN
SampleFiles/Fonts/Lato/Lato-Regular.ttf
Normal file
Binary file not shown.
BIN
SampleFiles/Fonts/Lato/Lato-Thin.ttf
Normal file
BIN
SampleFiles/Fonts/Lato/Lato-Thin.ttf
Normal file
Binary file not shown.
BIN
SampleFiles/Fonts/Lato/Lato-ThinItalic.ttf
Normal file
BIN
SampleFiles/Fonts/Lato/Lato-ThinItalic.ttf
Normal file
Binary file not shown.
31
Sources/CLIToolCore/CLIToolCore.swift
Normal file
31
Sources/CLIToolCore/CLIToolCore.swift
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// CLIToolCore.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public class Shell {
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public static func shell(_ args: String...) -> (terminationStatus: Int32, output: String?) {
|
||||||
|
let task = Process()
|
||||||
|
task.launchPath = "/usr/bin/env"
|
||||||
|
task.arguments = args
|
||||||
|
|
||||||
|
let pipe = Pipe()
|
||||||
|
task.standardOutput = pipe
|
||||||
|
task.launch()
|
||||||
|
task.waitUntilExit()
|
||||||
|
|
||||||
|
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||||
|
|
||||||
|
guard let output: String = String(data: data, encoding: .utf8) else {
|
||||||
|
return (terminationStatus: task.terminationStatus, output: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (terminationStatus: task.terminationStatus, output: output)
|
||||||
|
}
|
||||||
|
}
|
26
Sources/FontToolCore/Extensions.swift
Normal file
26
Sources/FontToolCore/Extensions.swift
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// File.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
func removeCharacters(from forbiddenChars: CharacterSet) -> String {
|
||||||
|
let passed = self.unicodeScalars.filter { !forbiddenChars.contains($0) }
|
||||||
|
return String(String.UnicodeScalarView(passed))
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeCharacters(from: String) -> String {
|
||||||
|
return removeCharacters(from: CharacterSet(charactersIn: from))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Sequence where Iterator.Element: Hashable {
|
||||||
|
func unique() -> [Iterator.Element] {
|
||||||
|
var seen: [Iterator.Element: Bool] = [:]
|
||||||
|
return self.filter { seen.updateValue(true, forKey: $0) == nil }
|
||||||
|
}
|
||||||
|
}
|
59
Sources/FontToolCore/FontToolContentGenerator.swift
Normal file
59
Sources/FontToolCore/FontToolContentGenerator.swift
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// FontToolContentGenerator.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class FontToolContentGenerator {
|
||||||
|
|
||||||
|
static func getExtensionHeader(fontsNames: [String]) -> String {
|
||||||
|
"""
|
||||||
|
// Generated from FontToolCore
|
||||||
|
// \(fontsNames.joined(separator: " "))
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getFontNameEnum(fontsNames: [String]) -> String {
|
||||||
|
var enumDefinition = "\tenum FontName: String {"
|
||||||
|
|
||||||
|
fontsNames.forEach {
|
||||||
|
//debugPrint("Name: \($0.removeCharacters(from: "[]+-_"))")
|
||||||
|
enumDefinition += "\t\tcase \($0.removeCharacters(from: "[]+-_")) = \"\($0)\"\n"
|
||||||
|
}
|
||||||
|
enumDefinition += "\t}\n"
|
||||||
|
|
||||||
|
return enumDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getFontMethods(fontsNames: [String], isUIFontExtension: Bool) -> String {
|
||||||
|
var methods = "\t// MARK: - Getter\n"
|
||||||
|
|
||||||
|
fontsNames
|
||||||
|
.unique()
|
||||||
|
.forEach {
|
||||||
|
let fontNameSanitize = $0.removeCharacters(from: "[]+-_")
|
||||||
|
|
||||||
|
if isUIFontExtension {
|
||||||
|
methods += """
|
||||||
|
\n\tstatic let \(fontNameSanitize): ((_ size: CGFloat) -> UIFont) = { size in
|
||||||
|
\tUIFont(name: FontName.\(fontNameSanitize).rawValue, size: size)!
|
||||||
|
\t}\n
|
||||||
|
"""
|
||||||
|
} else {
|
||||||
|
methods += """
|
||||||
|
\n\tfunc \(fontNameSanitize)(withSize size: CGFloat) -> UIFont {
|
||||||
|
\tUIFont(name: FontName.\(fontNameSanitize).rawValue, size: size)!
|
||||||
|
\t}\n
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return methods
|
||||||
|
}
|
||||||
|
}
|
27
Sources/FontToolCore/FontToolError.swift
Normal file
27
Sources/FontToolCore/FontToolError.swift
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// File.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
|
||||||
|
enum FontToolError: Error {
|
||||||
|
case fcScan(String, Int32, String?)
|
||||||
|
case inputFolderNotFound(String)
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .fcScan(let path, let code, let output):
|
||||||
|
return """
|
||||||
|
Error while getting fontName (fc-scan --format %{postscriptname} \(path).
|
||||||
|
fc-scan exit with \(code) and output is: \(output ?? "no output")
|
||||||
|
"""
|
||||||
|
|
||||||
|
case .inputFolderNotFound(let inputFolder):
|
||||||
|
return "Input folder not found: \(inputFolder)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
Sources/FontToolCore/FontToolHelper.swift
Normal file
48
Sources/FontToolCore/FontToolHelper.swift
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//
|
||||||
|
// FontToolHelper.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CLIToolCore
|
||||||
|
|
||||||
|
class FontToolHelper {
|
||||||
|
static func getFontsData(fromInputFolder inputFolder: String) -> (fontsNames: [String], fontsFileNames: [String]) {
|
||||||
|
// Get a enumerator for all files
|
||||||
|
let fileManager = FileManager()
|
||||||
|
|
||||||
|
guard fileManager.fileExists(atPath: inputFolder) else {
|
||||||
|
FontTool.exit(withError: FontToolError.fcScan(path, task.terminationStatus, task.output))
|
||||||
|
}
|
||||||
|
|
||||||
|
let enumerator: FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: inputFolder)!
|
||||||
|
|
||||||
|
// Filters font files
|
||||||
|
let fontsFileNames: [String] = (enumerator.allObjects as! [String])
|
||||||
|
.filter {
|
||||||
|
if $0.hasSuffix(".ttf") || $0.hasSuffix(".otf") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get font name (font name and font file name can be different)
|
||||||
|
let fontsNames = fontsFileNames.compactMap { getFontName(atPath: "\(inputFolder)/\($0)") }
|
||||||
|
|
||||||
|
return (fontsNames: fontsNames, fontsFileNames: fontsFileNames)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func getFontName(atPath path: String) -> String {
|
||||||
|
//print("fc-scan --format %{postscriptname} \(path)")
|
||||||
|
// Get real font name
|
||||||
|
let task = Shell.shell("fc-scan", "--format", "%{postscriptname}", path)
|
||||||
|
|
||||||
|
guard let fontName = task.output, task.terminationStatus == 0 else {
|
||||||
|
FontTool.exit(withError: FontToolError.fcScan(path, task.terminationStatus, task.output))
|
||||||
|
}
|
||||||
|
|
||||||
|
return fontName
|
||||||
|
}
|
||||||
|
}
|
69
Sources/FontToolCore/main.swift
Normal file
69
Sources/FontToolCore/main.swift
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// FontTool.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by Thibaut Schmitt on 13/12/2021.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CLIToolCore
|
||||||
|
import ArgumentParser
|
||||||
|
|
||||||
|
struct FontTool: ParsableCommand {
|
||||||
|
static let defaultExtensionName = "UIFont"
|
||||||
|
|
||||||
|
@Argument(help: "Input folder where fonts to generate are.")
|
||||||
|
var inputFolder: String
|
||||||
|
|
||||||
|
@Option(help: "Path where to generate the extension.")
|
||||||
|
var extensionOutputPath: String
|
||||||
|
|
||||||
|
@Option(help: "Extension name. If not specified, it will generate an UIFont extension")
|
||||||
|
var extensionName: String = Self.defaultExtensionName
|
||||||
|
|
||||||
|
public func run() throws {
|
||||||
|
print("[FontTool] Starting font generation")
|
||||||
|
|
||||||
|
let fontsData = FontToolHelper.getFontsData(fromInputFolder: inputFolder)
|
||||||
|
|
||||||
|
let extensionHeader = FontToolContentGenerator.getExtensionHeader(fontsNames: fontsData.fontsNames)
|
||||||
|
let extensionDefinitionOpening = "extension \(extensionName) {\n"
|
||||||
|
let extensionFontsNamesEnum = FontToolContentGenerator.getFontNameEnum(fontsNames: fontsData.fontsNames)
|
||||||
|
let extensionFontsMethods = FontToolContentGenerator.getFontMethods(fontsNames: fontsData.fontsNames, isUIFontExtension: isUIFontExtension())
|
||||||
|
let extensionDefinitionClosing = "}"
|
||||||
|
|
||||||
|
generateExtensionFile(extensionHeader,
|
||||||
|
extensionDefinitionOpening,
|
||||||
|
extensionFontsNamesEnum,
|
||||||
|
extensionFontsMethods,
|
||||||
|
extensionDefinitionClosing)
|
||||||
|
|
||||||
|
print("[FontTool] Font generated")
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateExtensionFile(_ args: String...) {
|
||||||
|
// Create output path
|
||||||
|
let extensionFilePath = "\(extensionOutputPath)/\(extensionName)+Font.swift"
|
||||||
|
|
||||||
|
// Create file if not exists
|
||||||
|
let fileManager = FileManager()
|
||||||
|
if fileManager.fileExists(atPath: extensionFilePath) == false {
|
||||||
|
Shell.shell("touch", "\(extensionFilePath)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create extension content
|
||||||
|
let extensionContent = args.joined(separator: "\n")
|
||||||
|
|
||||||
|
// Write content
|
||||||
|
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
|
||||||
|
try! extensionContent.write(to: extensionFilePathURL, atomically: true, encoding: .utf8)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Helpers
|
||||||
|
|
||||||
|
private func isUIFontExtension() -> Bool {
|
||||||
|
extensionName == Self.defaultExtensionName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FontTool.main()
|
1
Sources/ResgenSwift/main.swift
Normal file
1
Sources/ResgenSwift/main.swift
Normal file
@ -0,0 +1 @@
|
|||||||
|
print("Welcome ResgenSwift")
|
47
Tests/ResgenSwiftTests/ResgenCLITests.swift
Normal file
47
Tests/ResgenSwiftTests/ResgenCLITests.swift
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import XCTest
|
||||||
|
import class Foundation.Bundle
|
||||||
|
|
||||||
|
final class ResgenCLITests: XCTestCase {
|
||||||
|
func testExample() throws {
|
||||||
|
// This is an example of a functional test case.
|
||||||
|
// Use XCTAssert and related functions to verify your tests produce the correct
|
||||||
|
// results.
|
||||||
|
|
||||||
|
// Some of the APIs that we use below are available in macOS 10.13 and above.
|
||||||
|
guard #available(macOS 10.13, *) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mac Catalyst won't have `Process`, but it is supported for executables.
|
||||||
|
#if !targetEnvironment(macCatalyst)
|
||||||
|
|
||||||
|
let fooBinary = productsDirectory.appendingPathComponent("ResgenCLI")
|
||||||
|
|
||||||
|
let process = Process()
|
||||||
|
process.executableURL = fooBinary
|
||||||
|
|
||||||
|
let pipe = Pipe()
|
||||||
|
process.standardOutput = pipe
|
||||||
|
|
||||||
|
try process.run()
|
||||||
|
process.waitUntilExit()
|
||||||
|
|
||||||
|
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||||
|
let output = String(data: data, encoding: .utf8)
|
||||||
|
|
||||||
|
XCTAssertEqual(output, "Hello, world!\n")
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns path to the built products directory.
|
||||||
|
var productsDirectory: URL {
|
||||||
|
#if os(macOS)
|
||||||
|
for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") {
|
||||||
|
return bundle.bundleURL.deletingLastPathComponent()
|
||||||
|
}
|
||||||
|
fatalError("couldn't find the products directory")
|
||||||
|
#else
|
||||||
|
return Bundle.main.bundleURL
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# https://developer.apple.com/library/content/qa/qa1964/_index.html#//apple_ref/doc/uid/DTS40017675-CH1-SOURCECODE2
|
|
||||||
|
|
||||||
for fmk in $(find Carthage/Build -type f -perm -a=x) ; do
|
|
||||||
echo $fmk && nm -m -arch all $fmk | grep __llvm_prf
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
export PATH=~/scripts/fakeswiftlint:$PATH
|
|
||||||
|
|
||||||
carthage update $1 --platform iOS --no-use-binaries --no-build --use-submodules
|
|
||||||
|
|
||||||
# https://github.com/Carthage/Carthage/issues/2056 & https://stackoverflow.com/questions/46160518/xcode-9-carthage-itunes-connect-error-invalid-bundle-disallowed-llvm-instr
|
|
||||||
#find Carthage -type f -name "*.xcscheme" -print0 | xargs -0 perl -pi -e 's/codeCoverageEnabled = "YES"/codeCoverageEnabled = "NO"/g'
|
|
||||||
|
|
||||||
carthage build $1 --platform iOS --no-use-binaries --cache-builds
|
|
@ -1,189 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [[ "$BUILD_DIR" == *"IBDesignables"* ]] || [[ "$BUILD_DIR" == *"Previews"* ]] ; then
|
|
||||||
echo "do nothing when building for IBDesignables/SwiftUI Previews builds";
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$CONFIGURATION" != "Release" ]; then
|
|
||||||
# if [ "$(whoami)" == "hudson" ] || [ "$(whoami)" == "jenkins" ]; then
|
|
||||||
export PATH=/opt/local/bin/:/opt/local/sbin:$PATH:/usr/local/bin:
|
|
||||||
|
|
||||||
convertPath=`which convert`
|
|
||||||
gsPath=`which gs`
|
|
||||||
|
|
||||||
if [[ ! -f ${convertPath} || -z ${convertPath} ]]; then
|
|
||||||
convertValidation=true;
|
|
||||||
else
|
|
||||||
convertValidation=false;
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -f ${gsPath} || -z ${gsPath} ]]; then
|
|
||||||
gsValidation=true;
|
|
||||||
else
|
|
||||||
gsValidation=false;
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$convertValidation" = true || "$gsValidation" = true ]]; then
|
|
||||||
echo "WARNING: Skipping Icon versioning, you need to install ImageMagick and ghostscript (fonts) first, you can use brew to simplify process:"
|
|
||||||
|
|
||||||
if [[ "$convertValidation" = true ]]; then
|
|
||||||
echo "brew install imagemagick"
|
|
||||||
fi
|
|
||||||
if [[ "$gsValidation" = true ]]; then
|
|
||||||
echo "brew install ghostscript"
|
|
||||||
fi
|
|
||||||
exit 0;
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$MARKETING_VERSION" ]] ; then
|
|
||||||
version="$MARKETING_VERSION"
|
|
||||||
else
|
|
||||||
version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${INFOPLIST_FILE}")
|
|
||||||
fi
|
|
||||||
build_num=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${INFOPLIST_FILE}")
|
|
||||||
|
|
||||||
# Check if we are under a Git repo
|
|
||||||
if [ -d .git ] || git rev-parse --git-dir > /dev/null 2>&1; then
|
|
||||||
commit=`git rev-parse --short HEAD`
|
|
||||||
branch=`git rev-parse --abbrev-ref HEAD`
|
|
||||||
else
|
|
||||||
# Check if we are under a Git repo
|
|
||||||
|
|
||||||
svn info >/dev/null 2>&1
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
commit=`svnversion -n`
|
|
||||||
branch=`svn info | grep '^URL:' | egrep -o '(tags|branches)/[^/]+|trunk' | egrep -o '[^/]+$'`
|
|
||||||
fi
|
|
||||||
fi;
|
|
||||||
|
|
||||||
#SRCROOT=..
|
|
||||||
#CONFIGURATION_BUILD_DIR=.
|
|
||||||
#UNLOCALIZED_RESOURCES_FOLDER_PATH=.
|
|
||||||
|
|
||||||
#commit="3783bab"
|
|
||||||
#branch="master"
|
|
||||||
#version="3.4"
|
|
||||||
#build_num="9999"
|
|
||||||
|
|
||||||
shopt -s extglob
|
|
||||||
build_num="${build_num##*( )}"
|
|
||||||
shopt -u extglob
|
|
||||||
version_caption="${version}-dev"
|
|
||||||
if [ ! -z $HUMANVERSION ] ; then
|
|
||||||
version_caption="$HUMANVERSION"
|
|
||||||
fi
|
|
||||||
caption="$version_caption\nr${commit}"
|
|
||||||
echo $caption
|
|
||||||
|
|
||||||
function abspath() { pushd . > /dev/null; if [ -d "$1" ]; then cd "$1"; dirs -l +0; else cd "`dirname \"$1\"`"; cur_dir=`dirs -l +0`; if [ "$cur_dir" == "/" ]; then echo "$cur_dir`basename \"$1\"`"; else echo "$cur_dir/`basename \"$1\"`"; fi; fi; popd > /dev/null; }
|
|
||||||
|
|
||||||
function processIcon() {
|
|
||||||
base_file=$1
|
|
||||||
|
|
||||||
cd "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
|
||||||
base_path=`find . -name ${base_file}`
|
|
||||||
|
|
||||||
real_path=$( abspath "${base_path}" )
|
|
||||||
echo "base path ${real_path}"
|
|
||||||
|
|
||||||
if [[ ! -f ${base_path} || -z ${base_path} ]]; then
|
|
||||||
return;
|
|
||||||
fi
|
|
||||||
|
|
||||||
# TODO: if they are the same we need to fix it by introducing temp
|
|
||||||
target_file=`basename $base_path`
|
|
||||||
target_path="${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/${target_file}"
|
|
||||||
|
|
||||||
base_tmp_normalizedFileName="${base_file%.*}-normalized.${base_file##*.}"
|
|
||||||
base_tmp_path=`dirname $base_path`
|
|
||||||
base_tmp_normalizedFilePath="${base_tmp_path}/${base_tmp_normalizedFileName}"
|
|
||||||
|
|
||||||
stored_original_file="${base_tmp_normalizedFilePath}-tmp"
|
|
||||||
if [[ -f ${stored_original_file} ]]; then
|
|
||||||
echo "found previous file at path ${stored_original_file}, using it as base"
|
|
||||||
mv "${stored_original_file}" "${base_path}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $CONFIGURATION = "Release" ]; then
|
|
||||||
cp "${base_path}" "$target_path"
|
|
||||||
return 0;
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Reverting optimized PNG to normal"
|
|
||||||
# Normalize
|
|
||||||
echo "xcrun -sdk iphoneos pngcrush -revert-iphone-optimizations -q ${base_path} ${base_tmp_normalizedFilePath}"
|
|
||||||
xcrun -sdk iphoneos pngcrush -revert-iphone-optimizations -q "${base_path}" "${base_tmp_normalizedFilePath}"
|
|
||||||
|
|
||||||
# move original pngcrush png to tmp file
|
|
||||||
echo "moving pngcrushed png file at ${base_path} to ${stored_original_file}"
|
|
||||||
#rm "$base_path"
|
|
||||||
mv "$base_path" "${stored_original_file}"
|
|
||||||
|
|
||||||
# Rename normalized png's filename to original one
|
|
||||||
echo "Moving normalized png file to original one ${base_tmp_normalizedFilePath} to ${base_path}"
|
|
||||||
mv "${base_tmp_normalizedFilePath}" "${base_path}"
|
|
||||||
|
|
||||||
width=`identify -format %w ${base_path}`
|
|
||||||
height=`identify -format %h ${base_path}`
|
|
||||||
band_height=$((($height * 47) / 100))
|
|
||||||
band_position=$(($height - $band_height))
|
|
||||||
text_position=$(($band_position - 3))
|
|
||||||
point_size=$(((17 * $width) / 100))
|
|
||||||
|
|
||||||
echo "Image dimensions ($width x $height) - band height $band_height @ $band_position - point size $point_size"
|
|
||||||
|
|
||||||
#
|
|
||||||
# blur band and text
|
|
||||||
#
|
|
||||||
convert ${base_path} -blur 10x8 /tmp/blurred.png
|
|
||||||
convert /tmp/blurred.png -gamma 0 -fill white -draw "rectangle 0,$band_position,$width,$height" /tmp/mask.png
|
|
||||||
convert -size ${width}x${band_height} xc:none -fill 'rgba(0,0,0,0.2)' -draw "rectangle 0,0,$width,$band_height" /tmp/labels-base.png
|
|
||||||
convert -background none -size ${width}x${band_height} -pointsize $point_size -fill white -gravity center -gravity South caption:"$caption" /tmp/labels.png
|
|
||||||
|
|
||||||
convert ${base_path} /tmp/blurred.png /tmp/mask.png -composite /tmp/temp.png
|
|
||||||
|
|
||||||
#
|
|
||||||
# compose final image
|
|
||||||
#
|
|
||||||
filename=New${base_file}
|
|
||||||
convert /tmp/temp.png /tmp/labels-base.png -geometry +0+$band_position -composite /tmp/labels.png -geometry +0+$text_position -geometry +${w}-${h} -composite "${target_path}"
|
|
||||||
|
|
||||||
#
|
|
||||||
# clean up
|
|
||||||
#
|
|
||||||
rm /tmp/temp.png
|
|
||||||
rm /tmp/labels-base.png
|
|
||||||
rm /tmp/labels.png
|
|
||||||
rm /tmp/blurred.png
|
|
||||||
rm /tmp/mask.png
|
|
||||||
|
|
||||||
echo "Overlayed ${target_path}"
|
|
||||||
}
|
|
||||||
|
|
||||||
icon_count=`/usr/libexec/PlistBuddy -c "Print CFBundleIcons:CFBundlePrimaryIcon:CFBundleIconFiles" "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}" | wc -l`
|
|
||||||
last_icon_index=$((${icon_count} - 2))
|
|
||||||
|
|
||||||
i=0
|
|
||||||
while [ $i -lt $last_icon_index ]; do
|
|
||||||
icon=`/usr/libexec/PlistBuddy -c "Print CFBundleIcons:CFBundlePrimaryIcon:CFBundleIconFiles:$i" "${CONFIGURATION_BUILD_DIR}/${INFOPLIST_PATH}"`
|
|
||||||
|
|
||||||
if [[ $icon == *.png ]] || [[ $icon == *.PNG ]]
|
|
||||||
then
|
|
||||||
processIcon $icon
|
|
||||||
else
|
|
||||||
processIcon "${icon}.png"
|
|
||||||
processIcon "${icon}@2x.png"
|
|
||||||
processIcon "${icon}@3x.png"
|
|
||||||
fi
|
|
||||||
let i=i+1
|
|
||||||
done
|
|
||||||
|
|
||||||
# Workaround to fix issue#16 to use wildcard * to actually find the file
|
|
||||||
# Only 72x72 and 76x76 that we need for ipad app icons
|
|
||||||
processIcon "AppIcon72x72~ipad*"
|
|
||||||
processIcon "AppIcon72x72@2x~ipad*"
|
|
||||||
processIcon "AppIcon76x76~ipad*"
|
|
||||||
processIcon "AppIcon76x76@2x~ipad*"
|
|
||||||
# fi
|
|
||||||
fi
|
|
@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [[ "$BUILD_DIR" == *"IBDesignables"* ]] || [[ "$BUILD_DIR" == *"Previews"* ]] ; then
|
|
||||||
echo "do nothing when building for IBDesignables/SwiftUI Previews builds";
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
export PATH=$PATH:/usr/local/bin/
|
|
||||||
command -v lizard >/dev/null 2>&1 || { echo >&2 "warning: You have to install lizard (see https://github.com/terryyin/lizard). Aborting."; exit 0; }
|
|
||||||
|
|
||||||
lizard -w -x "./Carthage/*" -x "./vendor/*" --CCN 12 --ignore_warnings 20 --working_threads 4
|
|
@ -1,16 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [[ "$BUILD_DIR" == *"IBDesignables"* ]] || [[ "$BUILD_DIR" == *"Previews"* ]] ; then
|
|
||||||
echo "do nothing when building for IBDesignables/SwiftUI Previews builds";
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [[ -z ${SKIP_OBJCLEAN} || ${SKIP_OBJCLEAN} != 1 ]]; then
|
|
||||||
if [[ -d "${LOCAL_APPS_DIR}/Objective-Clean.app" ]]; then
|
|
||||||
"${LOCAL_APPS_DIR}"/Objective-Clean.app/Contents/Resources/ObjClean.app/Contents/MacOS/ObjClean "${PROJECT_DIR}"?!vendor
|
|
||||||
else
|
|
||||||
echo "warning: You have to install and set up Objective-Clean to use its features!"
|
|
||||||
fi
|
|
||||||
fi
|
|
@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
${PROJECT_DIR}/scripts/swiftlint.sh
|
|
||||||
|
|
||||||
${PROJECT_DIR}/scripts/lizard.sh
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [[ "$BUILD_DIR" == *"IBDesignables"* ]] || [[ "$BUILD_DIR" == *"Previews"* ]] || [[ $ACTION == "install" ]] ; then
|
|
||||||
echo "do nothing when building for IBDesignables/SwiftUI Previews/archive builds";
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
find ${PROJECT_DIR}/resgen -name '*.txt' -exec touch {} \;
|
|
||||||
echo >&2 "`basename $0`:6: error: Touched all resgen txt files, configure all variables in resgen scripts" && exit 12
|
|
||||||
|
|
||||||
# Colors
|
|
||||||
${PROJECT_DIR}/resgen/colors/colors-ios-swift.sh
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
${PROJECT_DIR}/resgen/twine/twine-ios.sh
|
|
||||||
|
|
||||||
# Images
|
|
||||||
${PROJECT_DIR}/resgen/images/images-ios-swift.sh
|
|
||||||
|
|
||||||
# Secure
|
|
||||||
${PROJECT_DIR}/resgen/secure/secure-ios-swift.sh
|
|
||||||
|
|
||||||
# Tags
|
|
||||||
${PROJECT_DIR}/resgen/tags/tags-ios.sh
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
#set -x
|
|
||||||
set -e
|
|
||||||
# https://github.com/plu/parallel_ios_tests
|
|
||||||
|
|
||||||
# Add this command line arg to your scheme : ${COMMANDLINE_APP_ARGUMENTS}
|
|
||||||
# To have a list of available devicetypes :
|
|
||||||
# xcrun simctl list devicetypes
|
|
||||||
echo "set devicetypes/languages/scheme(s) before launching this script" ; exit 12
|
|
||||||
declare -a devicetypes=("iPhone-4s" "iPhone-5" "iPhone-6" "iPhone-6-Plus")
|
|
||||||
declare -a languages=("fr" "en")
|
|
||||||
declare -a schemes=("TODO")
|
|
||||||
|
|
||||||
for scheme in "${schemes[@]}"; do
|
|
||||||
xcodebuild build -sdk iphonesimulator -scheme $scheme -derivedDataPath ./DerivedData ONLY_ACTIVE_ARCH=NO RUN_CLANG_STATIC_ANALYZER=NO VALID_ARCHS="i386 x86_64" ARCHS="i386 x86_64" | xcpretty
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Finished initial project compilation"
|
|
||||||
|
|
||||||
## now loop through the devices / langs / schemes (e.g. apps)
|
|
||||||
for device in "${devicetypes[@]}"; do
|
|
||||||
set +e
|
|
||||||
xcrun simctl shutdown screenshot_$device
|
|
||||||
xcrun simctl delete screenshot_$device
|
|
||||||
set -e
|
|
||||||
RUNTIME=$(xcrun simctl list runtimes | grep "com.apple.CoreSimulator.SimRuntime.iOS" | awk '{print $NF}')
|
|
||||||
UDID=$(xcrun simctl create screenshot_$device com.apple.CoreSimulator.SimDeviceType.$device $RUNTIME)
|
|
||||||
|
|
||||||
for lang in "${languages[@]}"; do
|
|
||||||
for scheme in "${schemes[@]}"; do
|
|
||||||
COMMANDLINE_APP_ARGUMENTS="-AppleLanguages ($lang)" xcodebuild test -scheme $scheme -destination name="screenshot_$device" -derivedDataPath ./DerivedData -only-testing:OTKTestAppTests/OTKScreenshotsTests RUN_CLANG_STATIC_ANALYZER=NO | xcpretty
|
|
||||||
mkdir -p screenshots/${scheme}_$lang/$device
|
|
||||||
mv /tmp/${scheme}*.jpg screenshots/${scheme}_$lang/$device/
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
set +e
|
|
||||||
xcrun simctl shutdown screenshot_$device
|
|
||||||
xcrun simctl delete screenshot_$device
|
|
||||||
set -e
|
|
||||||
done
|
|
@ -1,48 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Go to git repo root level
|
|
||||||
cd $(git rev-parse --show-toplevel)
|
|
||||||
|
|
||||||
if [[ "$BUILD_DIR" == *"IBDesignables"* ]] || [[ "$BUILD_DIR" == *"Previews"* ]] ; then
|
|
||||||
echo "not linting for IBDesignables/SwiftUI Previews builds";
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
SWIFT_LINT=$(which swiftlint)
|
|
||||||
|
|
||||||
if [[ -z $SWIFT_LINT ]] ; then
|
|
||||||
echo "warning: SwiftLint not installed, please download it from https://github.com/realm/SwiftLint"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $RUN_CLANG_STATIC_ANALYZER == "YES" ]] ; then
|
|
||||||
time $SWIFT_LINT
|
|
||||||
else
|
|
||||||
COUNT=0
|
|
||||||
|
|
||||||
##### Check for modified git files #####
|
|
||||||
FILES=$(git diff --name-only | grep -iv "^carthage" | grep -iv "^pods" | grep -iv "^vendor" | grep -v "R2" | grep ".swift$")
|
|
||||||
if [ ! -z "$FILES" ]; then
|
|
||||||
while read FILE_PATH; do
|
|
||||||
export SCRIPT_INPUT_FILE_$COUNT=$FILE_PATH
|
|
||||||
COUNT=$((COUNT + 1))
|
|
||||||
done <<< "$FILES"
|
|
||||||
fi
|
|
||||||
|
|
||||||
##### Check for modified files in unstaged/Staged area #####
|
|
||||||
FILES=$(git diff --name-only --cached --diff-filter=d | grep -iv "^carthage" | grep -iv "^pods" | grep -iv "^vendor" | grep -v "R2" | grep ".swift$")
|
|
||||||
if [ ! -z "$FILES" ]; then
|
|
||||||
while read FILE_PATH; do
|
|
||||||
export SCRIPT_INPUT_FILE_$COUNT=$FILE_PATH
|
|
||||||
COUNT=$((COUNT + 1))
|
|
||||||
done <<< "$FILES"
|
|
||||||
fi
|
|
||||||
|
|
||||||
##### Make the count avilable as global variable #####
|
|
||||||
export SCRIPT_INPUT_FILE_COUNT=$COUNT
|
|
||||||
env | grep SCRIPT_INPUT_FILE_
|
|
||||||
|
|
||||||
if [[ COUNT -ne 0 ]] ; then
|
|
||||||
time $SWIFT_LINT --use-script-input-files
|
|
||||||
fi
|
|
||||||
fi
|
|
@ -1,16 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [[ "$BUILD_DIR" == *"IBDesignables"* ]] || [[ "$BUILD_DIR" == *"Previews"* ]] ; then
|
|
||||||
echo "do nothing when building for IBDesignables/SwiftUI Previews builds";
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z ${SKIP_SWIFTCLEAN} || ${SKIP_SWIFTCLEAN} != 1 ]]; then
|
|
||||||
if [[ -d "${LOCAL_APPS_DIR}/Swiftly-Clean.app" ]]; then
|
|
||||||
"${LOCAL_APPS_DIR}"/Swiftly-Clean.app/Contents/Resources/SwiftClean.app/Contents/MacOS/SwiftClean "${SRCROOT}"
|
|
||||||
else
|
|
||||||
echo "warning: You have to install and set up Swift-Clean to use its features!"
|
|
||||||
fi
|
|
||||||
fi
|
|
@ -1,12 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [[ "$BUILD_DIR" == *"IBDesignables"* ]] || [[ "$BUILD_DIR" == *"Previews"* ]] ; then
|
|
||||||
echo "do nothing when building for IBDesignables/SwiftUI Previews builds";
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${CONFIGURATION}" = "Debug" ]; then
|
|
||||||
TAGS="TODO:|FIXME:|WARNING:"
|
|
||||||
echo "searching ${SRCROOT} for ${TAGS}"
|
|
||||||
find "${SRCROOT}" -type f -name "*.swift" ! -path "${SRCROOT}/vendor/*" ! -path "${SRCROOT}/build/*" ! -path "${SRCROOT}/DerivedData/*" ! -path "${SRCROOT}/Carthage/*" -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/"
|
|
||||||
fi
|
|
@ -1,33 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [[ "$BUILD_DIR" == *"IBDesignables"* ]] || [[ "$BUILD_DIR" == *"Previews"* ]] ; then
|
|
||||||
echo "do nothing when building for IBDesignables/SwiftUI Previews builds";
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [[ -z "$MARKETING_VERSION" ]] ; then
|
|
||||||
VERS="$MARKETING_VERSION"
|
|
||||||
else
|
|
||||||
VERS=$(/usr/libexec/PlistBuddy "${INFOPLIST_FILE}" -c "print CFBundleShortVersionString")
|
|
||||||
fi
|
|
||||||
REV=$(git rev-parse --short HEAD)
|
|
||||||
if [ "$?" -eq "0" ] && [ "$CONFIGURATION" == "Debug" ] ; then
|
|
||||||
REV=$VERS"-"$REV;
|
|
||||||
if ! git diff-index --quiet HEAD -- ; then
|
|
||||||
REV="$REV-mod"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
REV=$VERS;
|
|
||||||
fi
|
|
||||||
|
|
||||||
TMPFILE=$(mktemp /tmp/version.h.XXXXXXXXXX)
|
|
||||||
|
|
||||||
echo "#define AppVersionString @\"$REV\"" > $TMPFILE
|
|
||||||
|
|
||||||
if [[ ! -e ${PROJECT_DIR}/version.h ]] || [[ ! -z $(diff ${PROJECT_DIR}/version.h $TMPFILE) ]] ; then
|
|
||||||
mv $TMPFILE ${PROJECT_DIR}/version.h
|
|
||||||
else
|
|
||||||
rm $TMPFILE
|
|
||||||
fi
|
|
Loading…
x
Reference in New Issue
Block a user