File: Row.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 (151 lines) | stat: -rw-r--r-- 4,953 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
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
/*
 This source file is part of the Swift.org open source project

 Copyright (c) 2022-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
*/

import Foundation
import Markdown

/// A container directive that arranges content into a grid-based row and column
/// layout.
///
/// Create a new row by creating an `@Row` that contains child `@Column` directives.
///
/// ```md
/// @Row {
///    @Column {
///       @Image(source: "icon-power-icon", alt: "A blue square containing a snowflake.") {
///          Ice power
///       }
///    }
///
///    @Column {
///       @Image(source: "fire-power-icon", alt: "A red square containing a flame.") {
///          Fire power
///       }
///    }
///
///    @Column {
///       @Image(source: "wind-power-icon", alt: "A teal square containing a breath of air.") {
///          Wind power
///       }
///    }
///
///    @Column {
///       @Image(source: "lightning-power-icon", alt: "A yellow square containing a lightning bolt.") {
///          Lightning power
///       }
///    }
/// }
/// ```
///
/// ## Topics
///
/// - ``Column``
public final class Row: Semantic, AutomaticDirectiveConvertible, MarkupContaining {
    public static let introducedVersion = "5.8"
    public let originalMarkup: BlockDirective
    
    /// The number of columns available in this row.
    @DirectiveArgumentWrapped(name: .custom("numberOfColumns"))
    public private(set) var _numberOfColumns: Int? = nil
    
    /// The columns that make up this row.
    @ChildDirective(requirements: .oneOrMore)
    public private(set) var columns: [Column]
    
    static var keyPaths: [String : AnyKeyPath] = [
        "_numberOfColumns"   : \Row.__numberOfColumns,
        "columns"           : \Row._columns,
    ]
    
    /// The number of columns in this row.
    public var numberOfColumns: Int {
        // This may be different then the count of `columns` array. For example, there may be
        // individual columns that span multiple columns (specified with the column's
        // `size` argument) or the row could be not fully filled with columns.
        return _numberOfColumns ?? columns.map(\.size).reduce(0, +)
    }
    
    override var children: [Semantic] {
        return columns
    }
    
    var childMarkup: [Markup] {
        return columns.flatMap(\.childMarkup)
    }
    
    @available(*, deprecated,
        message: "Do not call directly. Required for 'AutomaticDirectiveConvertible'."
    )
    init(originalMarkup: BlockDirective) {
        self.originalMarkup = originalMarkup
    }
}

extension Row {
    /// A container directive that holds general markup content describing a column
    /// with a row in a grid-based layout.
    ///
    /// Create a column inside a ``Row`` by nesting a `@Column` directive within the content for an `@Row` directive.
    public final class Column: Semantic, AutomaticDirectiveConvertible, MarkupContaining {
        public static let introducedVersion = "5.8"
        public let originalMarkup: BlockDirective
        
        /// The size of this column.
        ///
        /// Specify a value greater than `1` to make this column span multiple columns
        /// in the parent ``Row``.
        @DirectiveArgumentWrapped
        public private(set) var size: Int = 1
        
        /// The markup content in this column.
        @ChildMarkup(numberOfParagraphs: .zeroOrMore, supportsStructure: true)
        public private(set) var content: MarkupContainer
        
        static var keyPaths: [String : AnyKeyPath] = [
            "size"      : \Column._size,
            "content"   : \Column._content,
        ]
        
        override var children: [Semantic] {
            return [content]
        }
        
        var childMarkup: [Markup] {
            return content.elements
        }
        
        @available(*, deprecated,
            message: "Do not call directly. Required for 'AutomaticDirectiveConvertible'."
        )
        init(originalMarkup: BlockDirective) {
            self.originalMarkup = originalMarkup
        }
    }
}

extension Row: RenderableDirectiveConvertible {
    func render(with contentCompiler: inout RenderContentCompiler) -> [RenderContent] {
        let renderedColumns = columns.map { column in
            return RenderBlockContent.Row.Column(
                size: column.size,
                content: column.content.elements.flatMap { markupElement in
                    return contentCompiler.visit(markupElement) as! [RenderBlockContent]
                }
            )
        }
        
        let renderedRow = RenderBlockContent.Row(
            numberOfColumns: numberOfColumns,
            columns: renderedColumns
        )
        
        return [RenderBlockContent.row(renderedRow)]
    }
}