File: Link.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (104 lines) | stat: -rw-r--r-- 3,550 bytes parent folder | download
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)
    }
}