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)]
}
}
|