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
|
/*
This source file is part of the Swift.org open source project
Copyright (c) 2021-2023 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 Swift project authors
*/
/// A link.
public struct Link: InlineMarkup, InlineContainer {
public var _data: _MarkupData
init(_ raw: RawMarkup) throws {
guard case .link = raw.data else {
throw RawMarkup.Error.concreteConversionError(from: raw, to: Link.self)
}
let absoluteRaw = AbsoluteRawMarkup(markup: raw, metadata: MarkupMetadata(id: .newRoot(), indexInParent: 0))
self.init(_MarkupData(absoluteRaw))
}
init(_ data: _MarkupData) {
self._data = data
}
}
// MARK: - Public API
public extension Link {
/// Create a link with a destination and zero or more child inline elements.
init<Children: Sequence>(destination: String? = nil, title: String? = nil, _ children: Children) where Children.Element == RecurringInlineMarkup {
let destinationToUse: String?
if let d = destination, d.isEmpty {
destinationToUse = nil
} else {
destinationToUse = destination
}
let titleToUse: String?
if let t = title, t.isEmpty {
titleToUse = nil
} else {
titleToUse = title
}
try! self.init(.link(destination: destinationToUse, title: titleToUse, parsedRange: nil, children.map { $0.raw.markup }))
}
/// Create a link with a destination and zero or more child inline elements.
init(destination: String, _ children: RecurringInlineMarkup...) {
self.init(destination: destination, children)
}
/// The link's destination.
var destination: String? {
get {
guard case let .link(destination, _) = _data.raw.markup.data else {
fatalError("\(self) markup wrapped unexpected \(_data.raw)")
}
return destination
}
set {
if let d = newValue, d.isEmpty {
_data = _data.replacingSelf(.link(destination: nil, title: title, parsedRange: nil, _data.raw.markup.copyChildren()))
} else {
_data = _data.replacingSelf(.link(destination: newValue, title: title, parsedRange: nil, _data.raw.markup.copyChildren()))
}
}
}
/// The link's title.
var title: String? {
get {
guard case let .link(_, title) = _data.raw.markup.data else {
fatalError("\(self) markup wrapped unexpected \(_data.raw)")
}
return title
}
set {
if let t = newValue, t.isEmpty {
_data = _data.replacingSelf(.link(destination: destination, title: nil, parsedRange: nil, _data.raw.markup.copyChildren()))
} else {
_data = _data.replacingSelf(.link(destination: destination, title: newValue, parsedRange: nil, _data.raw.markup.copyChildren()))
}
}
}
var isAutolink: Bool {
guard let destination = destination,
childCount == 1,
let text = child(at: 0) as? Text,
destination == text.string else {
return false
}
return true
}
// MARK: Visitation
func accept<V: MarkupVisitor>(_ visitor: inout V) -> V.Result {
return visitor.visitLink(self)
}
}
|