1- //
2- // Lyrics+Furigana.swift
3- // LyricsX - https://github.com/ddddxxx/LyricsX
4- //
5- // This Source Code Form is subject to the terms of the Mozilla Public
6- // License, v. 2.0. If a copy of the MPL was not distributed with this
7- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
8- //
9-
101#if canImport(Darwin)
112
123import Foundation
134import SwiftCF
145
156extension Lyrics {
16-
177 public func generateFurigana( ) {
188 for index in lines. indices {
199 lines [ index] . generateFurigana ( )
2010 }
2111 }
2212}
2313
24- private extension LyricsLine {
25-
26- mutating func generateFurigana( ) {
14+ extension LyricsLine {
15+ fileprivate mutating func generateFurigana( ) {
2716 var attachment = LyricsLine . Attachments. RangeAttribute ( attributes: [ ] )
2817 let tokenizer = CFStringTokenizer . create ( string: . from( content) )
2918 for tokenType in IteratorSequence ( tokenizer) where tokenType. contains ( . isCJWordMask) {
@@ -37,15 +26,14 @@ private extension LyricsLine {
3726 }
3827}
3928
40- private extension String {
41-
42- func characterRange( _ range: Range < String . Index > ) -> Range < Int > {
29+ extension String {
30+ fileprivate func characterRange( _ range: Range < String . Index > ) -> Range < Int > {
4331 let start = distance ( from: startIndex, to: range. lowerBound)
4432 let length = distance ( from: range. lowerBound, to: range. upperBound)
45- return start..< ( start + length)
33+ return start ..< ( start + length)
4634 }
47-
48- func transformLatinToHiragana( ) -> String ? {
35+
36+ fileprivate func transformLatinToHiragana( ) -> String ? {
4937 if #available( macOS 10 . 11 , iOS 9 . 0 , tvOS 9 . 0 , watchOS 2 . 0 , * ) {
5038 return applyingTransform ( . latinToHiragana, reverse: false )
5139 }
@@ -56,30 +44,28 @@ private extension String {
5644 }
5745}
5846
59- private extension CFStringTokenizer {
60-
61- func currentFuriganaAnnotation( in string: String ) -> ( String , Range < String . Index > ) ? {
47+ extension CFStringTokenizer {
48+ fileprivate func currentFuriganaAnnotation( in string: String ) -> ( String , Range < String . Index > ) ? {
6249 guard let tokenRange = Range ( currentTokenRange ( ) . asNS, in: string) else {
6350 return nil
6451 }
6552 let tokenStr = string [ tokenRange]
6653 guard tokenStr. unicodeScalars. contains ( where: CharacterSet . kanji. contains) ,
6754 let latin: String = currentTokenAttribute ( . latinTranscription) ? . asSwift ( ) ,
68- let hiragana = latin. transformLatinToHiragana ( ) ,
69- let ( rangeToAnnotate, rangeInAnnotation) = rangeOfUncommonContent ( tokenStr, hiragana) else {
70- return nil
55+ let hiragana = latin. transformLatinToHiragana ( ) ,
56+ let ( rangeToAnnotate, rangeInAnnotation) = rangeOfUncommonContent ( tokenStr, hiragana) else {
57+ return nil
7158 }
7259 let annotation = String ( hiragana [ rangeInAnnotation] )
7360 return ( annotation, rangeToAnnotate)
7461 }
7562}
7663
77- private extension CharacterSet {
78-
79- static let hiragana = CharacterSet ( charactersIn: " \u{3040} " ..< " \u{30a0} " )
80- static let katakana = CharacterSet ( charactersIn: " \u{30a0} " ..< " \u{3100} " )
81- static let kana = CharacterSet ( charactersIn: " \u{3040} " ..< " \u{3100} " )
82- static let kanji = CharacterSet ( charactersIn: " \u{4e00} " ..< " \u{9fc0} " )
64+ extension CharacterSet {
65+ fileprivate static let hiragana = CharacterSet ( charactersIn: " \u{3040} " ..< " \u{30a0} " )
66+ fileprivate static let katakana = CharacterSet ( charactersIn: " \u{30a0} " ..< " \u{3100} " )
67+ fileprivate static let kana = CharacterSet ( charactersIn: " \u{3040} " ..< " \u{3100} " )
68+ fileprivate static let kanji = CharacterSet ( charactersIn: " \u{4e00} " ..< " \u{9fc0} " )
8369}
8470
8571private func rangeOfUncommonContent< S1: StringProtocol , S2: StringProtocol > ( _ s1: S1 , _ s2: S2 ) -> ( Range < String . Index > , Range < String . Index > ) ? {
@@ -89,23 +75,23 @@ private func rangeOfUncommonContent<S1: StringProtocol, S2: StringProtocol>(_ s1
8975 var ( l1, l2) = ( s1. startIndex, s2. startIndex)
9076 while s1 [ l1] == s2 [ l2] {
9177 guard let nl1 = s1. index ( l1, offsetBy: 1 , limitedBy: s1. endIndex) ,
92- let nl2 = s2. index ( l2, offsetBy: 1 , limitedBy: s2. endIndex) else {
93- break
78+ let nl2 = s2. index ( l2, offsetBy: 1 , limitedBy: s2. endIndex) else {
79+ break
9480 }
9581 ( l1, l2) = ( nl1, nl2)
9682 }
97-
83+
9884 var ( r1, r2) = ( s1. endIndex, s2. endIndex)
9985 repeat {
10086 guard let nr1 = s1. index ( r1, offsetBy: - 1 , limitedBy: s1. startIndex) ,
101- let nr2 = s2. index ( r2, offsetBy: - 1 , limitedBy: s2. startIndex) else {
102- break
87+ let nr2 = s2. index ( r2, offsetBy: - 1 , limitedBy: s2. startIndex) else {
88+ break
10389 }
10490 ( r1, r2) = ( nr1, nr2)
10591 } while s1 [ r1] == s2 [ r2]
106-
107- let range1 = ( l1... r1) . relative ( to: s1. indices)
108- let range2 = ( l2... r2) . relative ( to: s2. indices)
92+
93+ let range1 = ( l1 ... r1) . relative ( to: s1. indices)
94+ let range2 = ( l2 ... r2) . relative ( to: s2. indices)
10995 return ( range1, range2)
11096}
11197
0 commit comments