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

 Copyright (c) 2021 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 section containing textual content and media laid out horizontally or vertically.
public struct ContentAndMediaSection: RenderSection, Equatable {
    public var kind: RenderSectionKind = .contentAndMedia
    
    /// The layout direction.
    public var layout: Layout?
    
    /// The title of the section.
    public var title: String?
    
    /// Text to display above the title.
    public var eyebrow: String?
    
    /// The body content of the section.
    public var content: [RenderBlockContent] = []
    
    /// An image or video to display opposite the text.
    public var media: RenderReferenceIdentifier?
    
    /// Whether the media comes before or after the text when read from top to bottom or leading to trailing.
    public var mediaPosition: ContentAndMedia.MediaPosition
    
    /// The kind of layout to use when rendering a section.
    /// Content is always leading, and media is always trailing.
    public enum Layout: String, Codable {
        /// Content should be laid out horizontally, with the media on the trailing side.
        case horizontal
        /// Content should be laid out vertically, with the media trailing the content.
        case vertical
    }
    
    /// Creates a new content and media section from the given parameters.
    ///
    /// - Parameters:
    ///   - layout: The layout direction for the section.
    ///   - title: The title of the section.
    ///   - media: A reference to a media item for the section.
    ///   - mediaPosition: The position of the media in relation to the prose content.
    public init(layout: Layout?, title: String?, media: RenderReferenceIdentifier?, mediaPosition: ContentAndMedia.MediaPosition) {
        self.layout = layout
        self.title = title
        self.media = media
        self.mediaPosition = mediaPosition
    }
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        kind = try container.decodeIfPresent(RenderSectionKind.self, forKey: .kind) ?? .contentAndMedia
        layout = try container.decodeIfPresent(Layout.self, forKey: .layout)
        title = try container.decodeIfPresent(String.self, forKey: .title)
        eyebrow = try container.decodeIfPresent(String.self, forKey: .eyebrow)
        content = try container.decodeIfPresent([RenderBlockContent].self, forKey: .content) ?? []
        media = try container.decodeIfPresent(RenderReferenceIdentifier.self, forKey: .media)
        mediaPosition = try container.decodeIfPresent(ContentAndMedia.MediaPosition.self, forKey: .mediaPosition)
        // Provide backwards-compatibility for ContentAndMediaSections that don't have a `mediaPosition` key.
        ?? .leading
    }
}
    
// Diffable conformance
extension ContentAndMediaSection: RenderJSONDiffable {
    /// Returns the differences between this ContentAndMediaSection and the given one.
    func difference(from other: ContentAndMediaSection, at path: CodablePath) -> JSONPatchDifferences {
        var diffBuilder = DifferenceBuilder(current: self, other: other, basePath: path)

        diffBuilder.addDifferences(atKeyPath: \.kind, forKey: CodingKeys.kind)
        diffBuilder.addDifferences(atKeyPath: \.layout, forKey: CodingKeys.layout)
        diffBuilder.addDifferences(atKeyPath: \.title, forKey: CodingKeys.title)
        diffBuilder.addDifferences(atKeyPath: \.eyebrow, forKey: CodingKeys.eyebrow)
        diffBuilder.addDifferences(atKeyPath: \.content, forKey: CodingKeys.content)
        diffBuilder.addDifferences(atKeyPath: \.media, forKey: CodingKeys.media)
        diffBuilder.addDifferences(atKeyPath: \.mediaPosition, forKey: CodingKeys.mediaPosition)

        return diffBuilder.differences
    }

    /// Returns if this ContentAndMediaSection is similar enough to the given one.
    func isSimilar(to other: ContentAndMediaSection) -> Bool {
        return self.title == other.title || self.content == other.content
    }
}