├── .gitignore ├── Logo.png ├── Sources └── Plot │ ├── Internal │ ├── AnyNode.swift │ ├── AnyEnvironmentValue.swift │ ├── AnyElement.swift │ ├── ModifiedComponent.swift │ ├── AnyAttribute.swift │ ├── ElementWrapper.swift │ ├── Environment.swift │ ├── String+Escaping.swift │ ├── ElementRenderingBuffer.swift │ └── Renderer.swift │ └── API │ ├── PodcastMediaType.swift │ ├── PodcastType.swift │ ├── Directionality.swift │ ├── Optional+Component.swift │ ├── HTMLAudioFormat.swift │ ├── DocumentEncoding.swift │ ├── HTMLVideoFormat.swift │ ├── PodcastEpisodeType.swift │ ├── HTMLButtonType.swift │ ├── TwitterCardType.swift │ ├── SiteMapChangeFrequency.swift │ ├── HTMLFormMethod.swift │ ├── XMLElements.swift │ ├── EmptyComponent.swift │ ├── URLRepresentable.swift │ ├── HTMLFormContentType.swift │ ├── HTMLViewportFitMode.swift │ ├── ElementClosingMode.swift │ ├── XMLAttributes.swift │ ├── HTMLInputType.swift │ ├── HTMLViewportWidthMode.swift │ ├── ElementDefinition.swift │ ├── HTMLAnchorTarget.swift │ ├── HTMLLinkRelationship.swift │ ├── ElementComponent.swift │ ├── PodcastAttributes.swift │ ├── Renderable.swift │ ├── RSSAttributes.swift │ ├── NodeConvertible.swift │ ├── EnvironmentValue.swift │ ├── PodcastComponents.swift │ ├── ComponentGroup.swift │ ├── XML.swift │ ├── SiteMap.swift │ ├── ComponentContainer.swift │ ├── ComponentBuilder.swift │ ├── Element.swift │ ├── Document.swift │ ├── SiteMapElements.swift │ ├── ControlFlow.swift │ ├── Attribute.swift │ ├── PodcastFeed.swift │ ├── Indentation.swift │ ├── HTMLAnchorRelationship.swift │ ├── HTMLListStyle.swift │ ├── RSS.swift │ ├── EnvironmentKey.swift │ ├── ComponentAttributes.swift │ ├── RSSElements.swift │ ├── Language.swift │ ├── Component.swift │ ├── PodcastElements.swift │ ├── Node.swift │ ├── HTML.swift │ └── HTMLElements.swift ├── Package.swift ├── Tests └── PlotTests │ ├── Require.swift │ ├── XMLTests.swift │ ├── ControlFlowTests.swift │ ├── Date+Stubbing.swift │ ├── IndentationTests.swift │ ├── SiteMapTests.swift │ ├── DocumentTests.swift │ ├── NodeTests.swift │ ├── RSSTests.swift │ ├── Assertions.swift │ ├── PodcastFeedTests.swift │ └── HTMLComponentTests.swift ├── LICENSE └── CONTRIBUTING.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /.swiftpm 4 | /*.xcodeproj 5 | -------------------------------------------------------------------------------- /Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JohnSundell/Plot/HEAD/Logo.png -------------------------------------------------------------------------------- /Sources/Plot/Internal/AnyNode.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2019 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | internal protocol AnyNode { 8 | func render(into renderer: inout Renderer) 9 | } 10 | -------------------------------------------------------------------------------- /Sources/Plot/Internal/AnyEnvironmentValue.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2021 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | internal protocol AnyEnvironmentValue { 8 | var environment: Environment.Reference { get } 9 | } 10 | -------------------------------------------------------------------------------- /Sources/Plot/API/PodcastMediaType.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2019 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | import Foundation 8 | 9 | /// Enum describing various podcast media types 10 | public enum PodcastMediaType: String { 11 | case audio 12 | case video 13 | } 14 | -------------------------------------------------------------------------------- /Sources/Plot/Internal/AnyElement.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2021 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | internal protocol AnyElement { 8 | var name: String { get } 9 | var closingMode: ElementClosingMode { get } 10 | var paddingCharacter: Character? { get } 11 | } 12 | -------------------------------------------------------------------------------- /Sources/Plot/API/PodcastType.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2019 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | import Foundation 8 | 9 | /// Enum describing various podcast types supported by Apple Podcasts. 10 | public enum PodcastType: String, Codable { 11 | case episodic 12 | case serial 13 | } 14 | -------------------------------------------------------------------------------- /Sources/Plot/API/Directionality.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2021 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | /// Enum defining an element's text directionality. 8 | public enum Directionality: String { 9 | case leftToRight = "ltr" 10 | case rightToLeft = "rtl" 11 | case auto = "auto" 12 | } 13 | -------------------------------------------------------------------------------- /Sources/Plot/API/Optional+Component.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2021 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | import Foundation 8 | 9 | extension Optional: Renderable, Component where Wrapped: Component { 10 | public var body: Component { 11 | self?.body ?? EmptyComponent() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Sources/Plot/API/HTMLAudioFormat.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2019 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | import Foundation 8 | 9 | /// Enum that defines various audio formats supported by most browsers. 10 | public enum HTMLAudioFormat: String, Codable { 11 | case mp3 = "mpeg" 12 | case wav 13 | case ogg 14 | } 15 | -------------------------------------------------------------------------------- /Sources/Plot/API/DocumentEncoding.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2019 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | import Foundation 8 | 9 | /// Enum defining possible encodings to use when rendering a document 10 | public enum DocumentEncoding: String { 11 | /// Use the UTF-8 Unicode encoding 12 | case utf8 = "UTF-8" 13 | } 14 | -------------------------------------------------------------------------------- /Sources/Plot/API/HTMLVideoFormat.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2019 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | import Foundation 8 | 9 | /// Enum that defines various video formats supported by most browsers. 10 | public enum HTMLVideoFormat: String, Codable { 11 | case mp4 12 | case webM = "webm" 13 | case ogg 14 | } 15 | -------------------------------------------------------------------------------- /Sources/Plot/Internal/ModifiedComponent.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2021 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | internal struct ModifiedComponent: Component { 8 | var base: Component 9 | var deferredAttributes = [AnyAttribute]() 10 | var environmentOverrides = [Environment.Override]() 11 | var body: Component { Node.modifiedComponent(self) } 12 | } 13 | -------------------------------------------------------------------------------- /Sources/Plot/API/PodcastEpisodeType.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2019 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | import Foundation 8 | 9 | /// Enum defining various podcast episode types that are supported 10 | /// by podcast players/systems such as Apple Podcasts. 11 | public enum PodcastEpisodeType: String { 12 | case full 13 | case trailer 14 | case bonus 15 | } 16 | -------------------------------------------------------------------------------- /Sources/Plot/API/HTMLButtonType.swift: -------------------------------------------------------------------------------- 1 | /** 2 | * Plot 3 | * Copyright (c) John Sundell 2019 4 | * MIT license, see LICENSE file for details 5 | */ 6 | 7 | import Foundation 8 | 9 | /// Enum that defines various button types that can be used with the 10 | /// `