1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#if canImport(TestSupport)
import TestSupport
#endif
#if FOUNDATION_FRAMEWORK
extension NSAttributedString.Key {
static let testInt = NSAttributedString.Key("TestInt")
static let testString = NSAttributedString.Key("TestString")
static let testDouble = NSAttributedString.Key("TestDouble")
static let testBool = NSAttributedString.Key("TestBool")
static let testParagraphConstrained = NSAttributedString.Key("TestParagraphConstrained")
static let testSecondParagraphConstrained = NSAttributedString.Key("TestSecondParagraphConstrained")
static let testCharacterConstrained = NSAttributedString.Key("TestCharacterConstrained")
}
#endif
extension AttributeScopes.TestAttributes {
enum TestIntAttribute: CodableAttributedStringKey {
typealias Value = Int
static let name = "TestInt"
}
enum TestStringAttribute: CodableAttributedStringKey {
typealias Value = String
static let name = "TestString"
}
enum TestDoubleAttribute: CodableAttributedStringKey {
typealias Value = Double
static let name = "TestDouble"
}
enum TestBoolAttribute: CodableAttributedStringKey {
typealias Value = Bool
static let name = "TestBool"
}
enum TestNonExtended: CodableAttributedStringKey {
typealias Value = Int
static let name = "TestNonExtended"
static let inheritedByAddedText: Bool = false
}
enum TestParagraphConstrained: CodableAttributedStringKey {
typealias Value = Int
static let name = "TestParagraphConstrained"
static let runBoundaries: AttributedString.AttributeRunBoundaries? = .paragraph
}
enum TestSecondParagraphConstrained: CodableAttributedStringKey {
typealias Value = Int
static let name = "TestSecondParagraphConstrained"
static let runBoundaries: AttributedString.AttributeRunBoundaries? = .paragraph
}
enum TestCharacterConstrained: CodableAttributedStringKey {
typealias Value = Int
static let name = "TestCharacterConstrained"
static let runBoundaries: AttributedString.AttributeRunBoundaries? = .character("*")
}
enum TestUnicodeCharacterConstrained: CodableAttributedStringKey {
typealias Value = Int
static let name = "TestUnicodeCharacterConstrained"
static let runBoundaries: AttributedString.AttributeRunBoundaries? = .character("\u{FFFD}") // U+FFFD Replacement Character
}
enum TestAttributeDependent: CodableAttributedStringKey {
typealias Value = Int
static let name = "TestAttributeDependent"
static let invalidationConditions: Set<AttributedString.AttributeInvalidationCondition>? = [.attributeChanged(\.testInt)]
}
enum TestCharacterDependent: CodableAttributedStringKey {
typealias Value = Int
static let name = "TestCharacterDependent"
static let invalidationConditions: Set<AttributedString.AttributeInvalidationCondition>? = [.textChanged]
}
enum NonCodableAttribute : AttributedStringKey {
typealias Value = NonCodableType
static let name = "NonCodable"
}
enum CustomCodableAttribute : CodableAttributedStringKey {
typealias Value = NonCodableType
static let name = "NonCodableConvertible"
static func encode(_ value: NonCodableType, to encoder: Encoder) throws {
var c = encoder.singleValueContainer()
try c.encode(value.inner)
}
static func decode(from decoder: Decoder) throws -> NonCodableType {
let c = try decoder.singleValueContainer()
let inner = try c.decode(Int.self)
return NonCodableType(inner: inner)
}
}
}
#if FOUNDATION_FRAMEWORK
extension AttributeScopes.TestAttributes.TestIntAttribute : MarkdownDecodableAttributedStringKey {}
extension AttributeScopes.TestAttributes.TestStringAttribute : MarkdownDecodableAttributedStringKey {}
extension AttributeScopes.TestAttributes.TestBoolAttribute : MarkdownDecodableAttributedStringKey {}
extension AttributeScopes.TestAttributes.TestDoubleAttribute : MarkdownDecodableAttributedStringKey {}
#endif // FOUNDATION_FRAMEWORK
struct NonCodableType : Hashable {
var inner : Int
}
extension AttributeScopes {
var test: TestAttributes.Type { TestAttributes.self }
struct TestAttributes : AttributeScope {
var testInt : TestIntAttribute
var testString : TestStringAttribute
var testDouble : TestDoubleAttribute
var testBool : TestBoolAttribute
var testNonExtended : TestNonExtended
var testParagraphConstrained : TestParagraphConstrained
var testSecondParagraphConstrained : TestSecondParagraphConstrained
var testCharacterConstrained : TestCharacterConstrained
var testUnicodeScalarConstrained : TestUnicodeCharacterConstrained
var testAttributeDependent : TestAttributeDependent
var testCharacterDependent : TestCharacterDependent
}
}
extension AttributeDynamicLookup {
subscript<T: AttributedStringKey>(dynamicMember keyPath: KeyPath<AttributeScopes.TestAttributes, T>) -> T {
get { self[T.self] }
}
}
enum TestError: Error {
case encodingError
case decodingError
case conversionError
case markdownError
}
#if !FOUNDATION_FRAMEWORK
extension AttributedStringProtocol {
func range(of other: String) -> Range<AttributedString.Index>? {
let str = String(characters)
guard let strRange = str.firstRange(of: other) else { return nil }
let start = str.unicodeScalars.distance(from: str.startIndex, to: strRange.lowerBound)
let end = str.unicodeScalars.distance(from: str.startIndex, to: strRange.upperBound)
return unicodeScalars.index(startIndex, offsetBy: start) ..< unicodeScalars.index(startIndex, offsetBy: end)
}
}
#endif // !FOUNDATION_FRAMEWORK
|