diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/EmojiSourceKit.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/EmojiSourceKit.xcscheme
index 463a67e..c411603 100644
--- a/.swiftpm/xcode/xcshareddata/xcschemes/EmojiSourceKit.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/EmojiSourceKit.xcscheme
@@ -50,6 +50,12 @@
ReferencedContainer = "container:">
+
+
+
+
Version {
if #available(iOS 17.4, *) {
return .v15_1
@@ -48,34 +50,55 @@ public enum EmojiManager {
/// Returns all emojis for a specific version
/// - Parameters:
/// - version: The specific version you want to fetch (default: the highest supported version for a device's iOS version)
- /// - showAllVariations: Some emojis inlcude skin type variations which increases the number of emojis drastically. (default: only the yellow neutral emojis are returned)
+ /// - showAllVariations: Some emojis include skin type variations which increases the number of emojis drastically. (default: only the yellow neutral emojis are returned)
/// - url: Specify the location of the `emoji_v.json` files if needed (default: bundle resource path)
/// - Returns: Array of categories with all emojis that are assigned to each category
public static func getAvailableEmojis(version: Version = .getSupportedVersion(), showAllVariations: Bool = false, at url: URL? = nil) -> [EmojiCategory] {
let fileUrl = url ?? Bundle.module.url(forResource: version.fileName, withExtension: "json")
- if let url = fileUrl, let content = try? Data(contentsOf: url), let result = try? JSONDecoder().decode([EmojiCategory].self, from: content) {
- var filteredEmojis: [EmojiCategory] = []
+ if let url = fileUrl, let content = try? Data(contentsOf: url), let result = try? JSONDecoder().decode([UnicodeEmojiCategory].self, from: content) {
+ var filteredEmojis: [UnicodeEmojiCategory] = []
+ var appleCategories: [AppleEmojiCategory] = []
for category in result {
let supportedEmojis = category.values.filter({
showAllVariations ? true : isNeutralEmoji(for: $0)
})
- filteredEmojis.append(EmojiCategory(name: category.name, values: supportedEmojis))
+ let unicodeCategory = UnicodeEmojiCategory(name: category.name, values: supportedEmojis)
+ filteredEmojis.append(unicodeCategory)
+
+ if shouldMergeCategory(category), let index = appleCategories.firstIndex(where: { $0.name == .smileysAndPeople }) {
+ if category.name == .smileysAndEmotions {
+ let oldValues = appleCategories[index].values
+ appleCategories[index].values = supportedEmojis
+ appleCategories[index].values.append(contentsOf: oldValues)
+ } else {
+ appleCategories[index].values.append(contentsOf: supportedEmojis)
+ }
+ } else {
+ guard let appleCategory = unicodeCategory.appleCategory else {
+ continue
+ }
+ appleCategories.append(AppleEmojiCategory(name: appleCategory, values: supportedEmojis))
+ }
}
- return filteredEmojis
+ return appleCategories.sorted(by: { $0.name.order < $1.name.order })
}
return []
}
-
+
+ private static func shouldMergeCategory(_ category: UnicodeEmojiCategory) -> Bool {
+ return category.name == .smileysAndEmotions || category.name == .peopleAndBody
+ }
+
private static func isNeutralEmoji(for emoji: String) -> Bool {
let unicodes = getUnicodes(emoji: emoji)
let colors = ["1F3FB", "1F3FC", "1F3FD", "1F3FE", "1F3FF"]
-
+
for color in colors where unicodes.contains(color) {
return false
}
return true
}
-
+
private static func getUnicodes(emoji: String) -> [String] {
let unicodeScalars = emoji.unicodeScalars
let unicodes = unicodeScalars.map { $0.value }
diff --git a/Sources/EmojiKit/EmojiCategory.swift b/Sources/EmojiKit/UnicodeEmojiCategory.swift
similarity index 56%
rename from Sources/EmojiKit/EmojiCategory.swift
rename to Sources/EmojiKit/UnicodeEmojiCategory.swift
index e068644..5c28693 100644
--- a/Sources/EmojiKit/EmojiCategory.swift
+++ b/Sources/EmojiKit/UnicodeEmojiCategory.swift
@@ -1,5 +1,5 @@
//
-// EmojiCategory.swift
+// UnicodeEmojiCategory.swift
//
//
// Created by Niklas Amslgruber on 10.06.23.
@@ -7,7 +7,7 @@
import Foundation
-public class EmojiCategory: Codable {
+public class UnicodeEmojiCategory: Codable {
public enum Name: String, CaseIterable, Codable {
case flags = "Flags"
@@ -21,47 +21,39 @@ public class EmojiCategory: Codable {
case foodAndDrink = "Food & Drink"
case smileysAndEmotions = "Smileys & Emotion"
- public static var orderedCases: [EmojiCategory.Name] {
- return EmojiCategory.Name.allCases.sorted(by: { $0.order < $1.order })
- }
-
- // The component category does not include relevant emojis
- public static var relevantCases: [EmojiCategory.Name] {
- return EmojiCategory.Name.orderedCases.filter({ $0 != .components })
- }
-
- // Order that Apple uses in their emoji picker
- public var order: Int {
+ var appleName: AppleEmojiCategory.Name? {
switch self {
case .flags:
- return 10
+ return .flags
case .activities:
- return 5
+ return .activity
case .components:
- return 8
+ return nil
case .objects:
- return 7
+ return .objects
case .travelAndPlaces:
- return 6
+ return .travelAndPlaces
case .symbols:
- return 9
+ return .symbols
case .peopleAndBody:
- return 2
+ return .smileysAndPeople
case .animalsAndNature:
- return 3
+ return .animalsAndNature
case .foodAndDrink:
- return 4
+ return .foodAndDrink
case .smileysAndEmotions:
- return 1
+ return .smileysAndPeople
}
}
}
public let name: Name
- public let values: [String]
+ public let appleCategory: AppleEmojiCategory.Name?
+ public var values: [String]
public init(name: Name, values: [String]) {
self.name = name
+ self.appleCategory = name.appleName
self.values = values
}
}
diff --git a/Sources/EmojiSourceKit/EmojiDownloader.swift b/Sources/EmojiSourceKit/EmojiDownloader.swift
index 6eae9ff..5c9dc58 100644
--- a/Sources/EmojiSourceKit/EmojiDownloader.swift
+++ b/Sources/EmojiSourceKit/EmojiDownloader.swift
@@ -47,9 +47,9 @@ struct EmojiDownloader: ParsableCommand, AsyncParsableCommand {
let parser = UnicodeParser()
do {
- let emojisByCategory: [EmojiCategory] = try await parser.parseEmojiList(for: emojiListURL)
+ let emojisByCategory: [UnicodeEmojiCategory] = try await parser.parseEmojiList(for: emojiListURL)
- let emojiCounts: [EmojiCategory.Name: Int] = parser.parseCountHTML(for: emojiCountsURL)
+ let emojiCounts: [UnicodeEmojiCategory.Name: Int] = parser.parseCountHTML(for: emojiCountsURL)
for category in emojisByCategory {
assert(emojiCounts[category.name] == category.values.count)
@@ -94,7 +94,7 @@ struct EmojiDownloader: ParsableCommand, AsyncParsableCommand {
}
}
- private func save(data: [EmojiCategory], for: EmojiManager.Version) {
+ private func save(data: [UnicodeEmojiCategory], for: EmojiManager.Version) {
let directory = getPath()
let encoder = JSONEncoder()
diff --git a/Sources/EmojiSourceKit/UnicodeParser.swift b/Sources/EmojiSourceKit/UnicodeParser.swift
index f885f13..39bfbbb 100644
--- a/Sources/EmojiSourceKit/UnicodeParser.swift
+++ b/Sources/EmojiSourceKit/UnicodeParser.swift
@@ -18,10 +18,10 @@ class UnicodeParser {
case minimallyQualified = "minimally-qualified"
}
- func parseEmojiList(for fileUrl: URL) async throws -> [EmojiCategory] {
+ func parseEmojiList(for fileUrl: URL) async throws -> [UnicodeEmojiCategory] {
let handle = try FileHandle(forReadingFrom: fileUrl)
- var currentGroup: EmojiCategory.Name = .activities
- var emojisByGroup: [EmojiCategory.Name: [String]] = [:]
+ var currentGroup: UnicodeEmojiCategory.Name = .activities
+ var emojisByGroup: [UnicodeEmojiCategory.Name: [String]] = [:]
for try await line in handle.bytes.lines {
@@ -34,7 +34,7 @@ class UnicodeParser {
if isLine(line, ofType: .group) {
let name = line.split(separator: ":")
let categoryName = name.last?.trim() ?? ""
- guard let category = EmojiCategory.Name(rawValue: categoryName) else {
+ guard let category = UnicodeEmojiCategory.Name(rawValue: categoryName) else {
continue
}
currentGroup = category
@@ -79,15 +79,15 @@ class UnicodeParser {
}
try handle.close()
- var result: [EmojiCategory] = []
+ var result: [UnicodeEmojiCategory] = []
- for category in EmojiCategory.Name.allCases {
- result.append(EmojiCategory(name: category, values: emojisByGroup[category] ?? []))
+ for category in UnicodeEmojiCategory.Name.allCases {
+ result.append(UnicodeEmojiCategory(name: category, values: emojisByGroup[category] ?? []))
}
return result
}
- func parseCountHTML(for url: URL) -> [EmojiCategory.Name: Int] {
+ func parseCountHTML(for url: URL) -> [UnicodeEmojiCategory.Name: Int] {
do {
let html = try String(contentsOf: url)
let doc: Document = try SwiftSoup.parse(html)
@@ -104,14 +104,14 @@ class UnicodeParser {
return [:]
}
- var categoryNames: [EmojiCategory.Name] = []
+ var categoryNames: [UnicodeEmojiCategory.Name] = []
var countNumbers: [Int] = []
for categoryElement in categoryEntries {
if categoryElement == categoryEntries.first || categoryElement == categoryEntries.last {
continue
}
- guard let text = try? categoryElement.text(), let category = EmojiCategory.Name(rawValue: text) else {
+ guard let text = try? categoryElement.text(), let category = UnicodeEmojiCategory.Name(rawValue: text) else {
continue
}
categoryNames.append(category)
@@ -127,7 +127,7 @@ class UnicodeParser {
countNumbers.append(number)
}
- var result: [EmojiCategory.Name: Int] = [:]
+ var result: [UnicodeEmojiCategory.Name: Int] = [:]
for (index, categoryName) in categoryNames.enumerated() {
result[categoryName] = countNumbers[index]