Tekkon // v1.5.1 Update, removing Foundation dependency.
This commit is contained in:
parent
7ef7f33993
commit
86b8fa5f79
|
@ -6,8 +6,6 @@
|
||||||
// marks, or product names of Contributor, except as required to fulfill notice
|
// marks, or product names of Contributor, except as required to fulfill notice
|
||||||
// requirements defined in MIT License.
|
// requirements defined in MIT License.
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
/// The namespace for this package.
|
/// The namespace for this package.
|
||||||
public enum Tekkon {
|
public enum Tekkon {
|
||||||
// MARK: - Static Constants
|
// MARK: - Static Constants
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
// marks, or product names of Contributor, except as required to fulfill notice
|
// marks, or product names of Contributor, except as required to fulfill notice
|
||||||
// requirements defined in MIT License.
|
// requirements defined in MIT License.
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
public extension Tekkon {
|
public extension Tekkon {
|
||||||
// MARK: - Dynamic Constants and Basic Enums
|
// MARK: - Dynamic Constants and Basic Enums
|
||||||
|
|
||||||
|
@ -115,7 +113,7 @@ public extension Tekkon {
|
||||||
/// - strOf: 要取代的內容。
|
/// - strOf: 要取代的內容。
|
||||||
/// - strWith: 要取代成的內容。
|
/// - strWith: 要取代成的內容。
|
||||||
public mutating func selfReplace(_ strOf: String, _ strWith: String = "") {
|
public mutating func selfReplace(_ strOf: String, _ strWith: String = "") {
|
||||||
valueStorage = valueStorage.replacingOccurrences(of: strOf, with: strWith)
|
if valueStorage == strOf { valueStorage = strWith }
|
||||||
ensureType()
|
ensureType()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
// marks, or product names of Contributor, except as required to fulfill notice
|
// marks, or product names of Contributor, except as required to fulfill notice
|
||||||
// requirements defined in MIT License.
|
// requirements defined in MIT License.
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
public extension Tekkon {
|
public extension Tekkon {
|
||||||
// MARK: - Syllable Composer
|
// MARK: - Syllable Composer
|
||||||
|
|
||||||
|
@ -65,7 +63,7 @@ public extension Tekkon {
|
||||||
public func getComposition(isHanyuPinyin: Bool = false, isTextBookStyle: Bool = false) -> String {
|
public func getComposition(isHanyuPinyin: Bool = false, isTextBookStyle: Bool = false) -> String {
|
||||||
switch isHanyuPinyin {
|
switch isHanyuPinyin {
|
||||||
case false: // 注音輸出的場合
|
case false: // 注音輸出的場合
|
||||||
let valReturnZhuyin = value.replacingOccurrences(of: " ", with: "")
|
let valReturnZhuyin = value.swapping(" ", with: "")
|
||||||
return isTextBookStyle ? cnvPhonaToTextbookReading(target: valReturnZhuyin) : valReturnZhuyin
|
return isTextBookStyle ? cnvPhonaToTextbookReading(target: valReturnZhuyin) : valReturnZhuyin
|
||||||
case true: // 拼音輸出的場合
|
case true: // 拼音輸出的場合
|
||||||
let valReturnPinyin = Tekkon.cnvPhonaToHanyuPinyin(targetJoined: value)
|
let valReturnPinyin = Tekkon.cnvPhonaToHanyuPinyin(targetJoined: value)
|
||||||
|
@ -87,7 +85,7 @@ public extension Tekkon {
|
||||||
case "˙": toneReturned = "5"
|
case "˙": toneReturned = "5"
|
||||||
default: break
|
default: break
|
||||||
}
|
}
|
||||||
return romajiBuffer.replacingOccurrences(of: "v", with: "ü") + toneReturned
|
return romajiBuffer.swapping("v", with: "ü") + toneReturned
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 注拼槽內容是否為空。
|
/// 注拼槽內容是否為空。
|
||||||
|
@ -132,9 +130,17 @@ public extension Tekkon {
|
||||||
/// 注意:回傳結果會受到當前注音排列 parser 屬性的影響。
|
/// 注意:回傳結果會受到當前注音排列 parser 屬性的影響。
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - key: 傳入的 UniChar 內容。
|
/// - key: 傳入的 UniChar 內容。
|
||||||
public func inputValidityCheck(key inputKey: UniChar = 0) -> Bool {
|
public func inputValidityCheck(key inputKey: UInt16 = 0) -> Bool {
|
||||||
if let scalar = UnicodeScalar(inputKey) {
|
guard let scalar = UnicodeScalar(inputKey) else { return false }
|
||||||
let input = String(scalar)
|
return inputValidityCheck(charStr: String(scalar))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 用於檢測「某個輸入字符訊號的合規性」的函式。
|
||||||
|
///
|
||||||
|
/// 注意:回傳結果會受到當前注音排列 parser 屬性的影響。
|
||||||
|
/// - Parameters:
|
||||||
|
/// - charStr: 傳入的字元(String)。
|
||||||
|
public func inputValidityCheck(charStr input: String) -> Bool {
|
||||||
switch parser {
|
switch parser {
|
||||||
case .ofDachen:
|
case .ofDachen:
|
||||||
return Tekkon.mapQwertyDachen[input] != nil
|
return Tekkon.mapQwertyDachen[input] != nil
|
||||||
|
@ -159,13 +165,11 @@ public extension Tekkon {
|
||||||
case .ofAlvinLiu:
|
case .ofAlvinLiu:
|
||||||
return Tekkon.mapAlvinLiuStaticKeys[input] != nil
|
return Tekkon.mapAlvinLiuStaticKeys[input] != nil
|
||||||
case .ofWadeGilesPinyin:
|
case .ofWadeGilesPinyin:
|
||||||
return Tekkon.mapWadeGilesPinyinKeys.contains(input)
|
return Tekkon.mapWadeGilesPinyinKeys.has(string: input)
|
||||||
case .ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin:
|
case .ofHanyuPinyin, .ofSecondaryPinyin, .ofYalePinyin, .ofHualuoPinyin, .ofUniversalPinyin:
|
||||||
return Tekkon.mapArayuruPinyin.contains(input)
|
return Tekkon.mapArayuruPinyin.has(string: input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 按需更新拼音組音區的內容顯示。
|
/// 按需更新拼音組音區的內容顯示。
|
||||||
mutating func updateRomajiBuffer() {
|
mutating func updateRomajiBuffer() {
|
||||||
|
@ -222,7 +226,7 @@ public extension Tekkon {
|
||||||
/// 如果是諸如複合型注音排列的話,翻譯結果有可能為空,但翻譯過程已經處理好聲介韻調分配了。
|
/// 如果是諸如複合型注音排列的話,翻譯結果有可能為空,但翻譯過程已經處理好聲介韻調分配了。
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - fromCharCode: 傳入的 UniChar 內容。
|
/// - fromCharCode: 傳入的 UniChar 內容。
|
||||||
public mutating func receiveKey(fromCharCode inputCharCode: UniChar = 0) {
|
public mutating func receiveKey(fromCharCode inputCharCode: UInt16 = 0) {
|
||||||
if let scalar = UnicodeScalar(inputCharCode) {
|
if let scalar = UnicodeScalar(inputCharCode) {
|
||||||
receiveKey(fromString: String(scalar))
|
receiveKey(fromString: String(scalar))
|
||||||
}
|
}
|
||||||
|
@ -781,6 +785,6 @@ public extension Tekkon {
|
||||||
|
|
||||||
private extension String {
|
private extension String {
|
||||||
func doesHave(_ target: String) -> Bool {
|
func doesHave(_ target: String) -> Bool {
|
||||||
target.isEmpty ? isEmpty : contains(target)
|
has(string: target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
// marks, or product names of Contributor, except as required to fulfill notice
|
// marks, or product names of Contributor, except as required to fulfill notice
|
||||||
// requirements defined in MIT License.
|
// requirements defined in MIT License.
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
public extension Tekkon {
|
public extension Tekkon {
|
||||||
// MARK: - Phonabet to Hanyu-Pinyin Conversion Processing
|
// MARK: - Phonabet to Hanyu-Pinyin Conversion Processing
|
||||||
|
|
||||||
|
@ -17,7 +15,7 @@ public extension Tekkon {
|
||||||
static func cnvPhonaToHanyuPinyin(targetJoined: String) -> String {
|
static func cnvPhonaToHanyuPinyin(targetJoined: String) -> String {
|
||||||
var targetConverted = targetJoined
|
var targetConverted = targetJoined
|
||||||
for pair in arrPhonaToHanyuPinyin {
|
for pair in arrPhonaToHanyuPinyin {
|
||||||
targetConverted = targetConverted.replacingOccurrences(of: pair[0], with: pair[1])
|
targetConverted = targetConverted.swapping(pair[0], with: pair[1])
|
||||||
}
|
}
|
||||||
return targetConverted
|
return targetConverted
|
||||||
}
|
}
|
||||||
|
@ -28,7 +26,7 @@ public extension Tekkon {
|
||||||
static func cnvHanyuPinyinToTextbookStyle(targetJoined: String) -> String {
|
static func cnvHanyuPinyinToTextbookStyle(targetJoined: String) -> String {
|
||||||
var targetConverted = targetJoined
|
var targetConverted = targetJoined
|
||||||
for pair in arrHanyuPinyinTextbookStyleConversionTable {
|
for pair in arrHanyuPinyinTextbookStyleConversionTable {
|
||||||
targetConverted = targetConverted.replacingOccurrences(of: pair[0], with: pair[1])
|
targetConverted = targetConverted.swapping(pair[0], with: pair[1])
|
||||||
}
|
}
|
||||||
return targetConverted
|
return targetConverted
|
||||||
}
|
}
|
||||||
|
@ -54,7 +52,7 @@ public extension Tekkon {
|
||||||
target: String
|
target: String
|
||||||
) -> String {
|
) -> String {
|
||||||
var newNeta = target
|
var newNeta = target
|
||||||
if !"ˊˇˋ˙".contains(String(target.reversed()[0])), !target.contains("_") { newNeta += "1" }
|
if !"ˊˇˋ˙".has(string: String(target.reversed()[0])), !target.has(string: "_") { newNeta += "1" }
|
||||||
return newNeta
|
return newNeta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,11 +67,11 @@ public extension Tekkon {
|
||||||
var result = targetJoined
|
var result = targetJoined
|
||||||
for key in Tekkon.mapHanyuPinyin.keys.sorted(by: { $0.count > $1.count }) {
|
for key in Tekkon.mapHanyuPinyin.keys.sorted(by: { $0.count > $1.count }) {
|
||||||
guard let value = Tekkon.mapHanyuPinyin[key] else { continue }
|
guard let value = Tekkon.mapHanyuPinyin[key] else { continue }
|
||||||
result = result.replacingOccurrences(of: key, with: value)
|
result = result.swapping(key, with: value)
|
||||||
}
|
}
|
||||||
for key in Tekkon.mapArayuruPinyinIntonation.keys.sorted(by: { $0.count > $1.count }) {
|
for key in Tekkon.mapArayuruPinyinIntonation.keys.sorted(by: { $0.count > $1.count }) {
|
||||||
guard let value = Tekkon.mapArayuruPinyinIntonation[key] else { continue }
|
guard let value = Tekkon.mapArayuruPinyinIntonation[key] else { continue }
|
||||||
result = result.replacingOccurrences(of: key, with: (key == "1") ? newToneOne : value)
|
result = result.swapping(key, with: (key == "1") ? newToneOne : value)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -82,8 +80,82 @@ public extension Tekkon {
|
||||||
/// 檢測字串是否包含半形英數內容
|
/// 檢測字串是否包含半形英數內容
|
||||||
private extension String {
|
private extension String {
|
||||||
var isNotPureAlphanumerical: Bool {
|
var isNotPureAlphanumerical: Bool {
|
||||||
let regex = ".*[^A-Za-z0-9].*"
|
let x = unicodeScalars.map(\.value).filter {
|
||||||
let testString = NSPredicate(format: "SELF MATCHES %@", regex)
|
if $0 >= 48, $0 <= 57 { return false }
|
||||||
return testString.evaluate(with: self)
|
if $0 >= 65, $0 <= 90 { return false }
|
||||||
|
if $0 >= 97, $0 <= 122 { return false }
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return !x.isEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This package is trying to deprecate its dependency of Foundation, hence the following contents.
|
||||||
|
|
||||||
|
extension StringProtocol {
|
||||||
|
func has(string target: any StringProtocol) -> Bool {
|
||||||
|
let selfArray = Array(unicodeScalars)
|
||||||
|
let targetArray = Array(target.description.unicodeScalars)
|
||||||
|
guard !target.isEmpty else { return isEmpty }
|
||||||
|
guard count >= target.count else { return false }
|
||||||
|
for index in 0 ..< selfArray.count {
|
||||||
|
let range = index ..< (Swift.min(index + targetArray.count, selfArray.count))
|
||||||
|
let ripped = Array(selfArray[range])
|
||||||
|
if ripped == targetArray { return true }
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func sliced(by separator: any StringProtocol = "") -> [String] {
|
||||||
|
let selfArray = Array(unicodeScalars)
|
||||||
|
let arrSeparator = Array(separator.description.unicodeScalars)
|
||||||
|
var result: [String] = []
|
||||||
|
var buffer: [Unicode.Scalar] = []
|
||||||
|
var sleepCount = 0
|
||||||
|
for index in 0 ..< selfArray.count {
|
||||||
|
let currentChar = selfArray[index]
|
||||||
|
let range = index ..< (Swift.min(index + arrSeparator.count, selfArray.count))
|
||||||
|
let ripped = Array(selfArray[range])
|
||||||
|
if ripped.isEmpty { continue }
|
||||||
|
if ripped == arrSeparator {
|
||||||
|
sleepCount = range.count
|
||||||
|
result.append(buffer.map { String($0) }.joined())
|
||||||
|
buffer.removeAll()
|
||||||
|
}
|
||||||
|
if sleepCount < 1 {
|
||||||
|
buffer.append(currentChar)
|
||||||
|
}
|
||||||
|
sleepCount -= 1
|
||||||
|
}
|
||||||
|
result.append(buffer.map { String($0) }.joined())
|
||||||
|
buffer.removeAll()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func swapping(_ target: String, with newString: String) -> String {
|
||||||
|
let selfArray = Array(unicodeScalars)
|
||||||
|
let arrTarget = Array(target.description.unicodeScalars)
|
||||||
|
var result = ""
|
||||||
|
var buffer: [Unicode.Scalar] = []
|
||||||
|
var sleepCount = 0
|
||||||
|
for index in 0 ..< selfArray.count {
|
||||||
|
let currentChar = selfArray[index]
|
||||||
|
let range = index ..< (Swift.min(index + arrTarget.count, selfArray.count))
|
||||||
|
let ripped = Array(selfArray[range])
|
||||||
|
if ripped.isEmpty { continue }
|
||||||
|
if ripped == arrTarget {
|
||||||
|
sleepCount = ripped.count
|
||||||
|
result.append(buffer.map { String($0) }.joined())
|
||||||
|
result.append(newString)
|
||||||
|
buffer.removeAll()
|
||||||
|
}
|
||||||
|
if sleepCount < 1 {
|
||||||
|
buffer.append(currentChar)
|
||||||
|
}
|
||||||
|
sleepCount -= 1
|
||||||
|
}
|
||||||
|
result.append(buffer.map { String($0) }.joined())
|
||||||
|
buffer.removeAll()
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue