File: TutorialArticleSection.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 (108 lines) | stat: -rw-r--r-- 3,799 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
/*
 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 Tutorial Article section.
public struct TutorialArticleSection: RenderSection, Equatable {
    
    public let kind: RenderSectionKind = .articleBody
    
    /// The contents of the Tutorial Article.
    public var content: [ContentLayout] = []
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        content = try container.decodeIfPresent([ContentLayout].self, forKey: .content) ?? []
    }
    
    /// Creates a tutorial article section from a given list
    /// of content layout items.
    ///
    /// - Parameter content: The content for this section.
    public init(content: [ContentLayout]) {
        self.content = content
    }
}

/// The layout in which the content should be presented.
public enum ContentLayout: Equatable {
    /// A full-width layout.
    case fullWidth(content: [RenderBlockContent])
    
    /// A layout for a piece of media that has an attached description.
    case contentAndMedia(content: ContentAndMediaSection)
    
    /// A multi-column layout.
    case columns(content: [ContentAndMediaSection])
}

extension ContentLayout: Codable {
    private enum CodingKeys: CodingKey {
        case kind
        case content
    }
    
    private enum LayoutKind: String, Codable {
        case fullWidth, contentAndMedia, columns
    }
    
    private var kind: LayoutKind {
        switch self {
        case .fullWidth: return .fullWidth
        case .contentAndMedia: return .contentAndMedia
        case .columns: return .columns
        }
    }
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let kind = try container.decode(LayoutKind.self, forKey: .kind)
        
        switch kind {
        case .fullWidth:
            self = try .fullWidth(content: container.decode([RenderBlockContent].self, forKey: .content))
        case .contentAndMedia:
            self = .contentAndMedia(content: try ContentAndMediaSection(from: decoder))
        case .columns:
            self = try .columns(content: container.decode([ContentAndMediaSection].self, forKey: .content))
        }
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(kind, forKey: .kind)
        
        switch self {
        case .fullWidth(let content):
            try container.encode(content, forKey: .content)
        case .contentAndMedia(let content):
            try content.encode(to: encoder)
        case .columns(let content):
            try container.encode(content, forKey: .content)
        }
    }
}

// Diffable conformance
extension TutorialArticleSection: RenderJSONDiffable {
    /// Returns the differences between this TutorialArticleSection and the given one.
    func difference(from other: TutorialArticleSection, at path: CodablePath) -> JSONPatchDifferences {
        var diffBuilder = DifferenceBuilder(current: self, other: other, basePath: path)

        diffBuilder.addDifferences(atKeyPath: \.kind, forKey: CodingKeys.kind)
        diffBuilder.addDifferences(atKeyPath: \.content, forKey: CodingKeys.content)

        return diffBuilder.differences
    }

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