feat: Working on documentation
This commit is contained in:
1
.prettierignore
Normal file
1
.prettierignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
**/*.docc
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
/// A result builder for creating ``TextNode`` types, similar to how
|
||||||
|
/// `ViewBuilder` works in `SwiftUI`.
|
||||||
|
///
|
||||||
@resultBuilder
|
@resultBuilder
|
||||||
public enum TextBuilder {
|
public enum TextBuilder {
|
||||||
|
|
||||||
@@ -7,27 +10,27 @@ public enum TextBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@inlinable
|
@inlinable
|
||||||
public static func buildPartialBlock<N0: TextNode, N1: TextNode>(accumulated: N0, next: N1) -> NodeContainer {
|
public static func buildPartialBlock<N0: TextNode, N1: TextNode>(accumulated: N0, next: N1) -> _NodeContainer {
|
||||||
.init(nodes: [accumulated, next])
|
.init(nodes: [accumulated, next])
|
||||||
}
|
}
|
||||||
|
|
||||||
@inlinable
|
@inlinable
|
||||||
public static func buildArray<N: TextNode>(_ components: [N]) -> NodeContainer {
|
public static func buildArray<N: TextNode>(_ components: [N]) -> _NodeContainer {
|
||||||
.init(nodes: components)
|
.init(nodes: components)
|
||||||
}
|
}
|
||||||
|
|
||||||
@inlinable
|
@inlinable
|
||||||
public static func buildBlock<N: TextNode>(_ components: N...) -> NodeContainer {
|
public static func buildBlock<N: TextNode>(_ components: N...) -> _NodeContainer {
|
||||||
.init(nodes: components)
|
.init(nodes: components)
|
||||||
}
|
}
|
||||||
|
|
||||||
@inlinable
|
@inlinable
|
||||||
public static func buildEither<N: TextNode, N1: TextNode>(first component: N) -> EitherNode<N, N1> {
|
public static func buildEither<N: TextNode, N1: TextNode>(first component: N) -> _EitherNode<N, N1> {
|
||||||
.first(component)
|
.first(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
@inlinable
|
@inlinable
|
||||||
public static func buildEither<N: TextNode, N1: TextNode>(second component: N1) -> EitherNode<N, N1> {
|
public static func buildEither<N: TextNode, N1: TextNode>(second component: N1) -> _EitherNode<N, N1> {
|
||||||
.second(component)
|
.second(component)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +41,8 @@ public enum TextBuilder {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum EitherNode<N: TextNode, N1: TextNode>: TextNode {
|
// swiftlint:disable type_name
|
||||||
|
public enum _EitherNode<N: TextNode, N1: TextNode>: TextNode {
|
||||||
case first(N)
|
case first(N)
|
||||||
case second(N1)
|
case second(N1)
|
||||||
|
|
||||||
@@ -50,7 +54,7 @@ public enum EitherNode<N: TextNode, N1: TextNode>: TextNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct NodeContainer: TextNode {
|
public struct _NodeContainer: TextNode {
|
||||||
|
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
var nodes: [any TextNode]
|
var nodes: [any TextNode]
|
||||||
@@ -58,7 +62,7 @@ public struct NodeContainer: TextNode {
|
|||||||
@usableFromInline
|
@usableFromInline
|
||||||
init(nodes: [any TextNode]) {
|
init(nodes: [any TextNode]) {
|
||||||
self.nodes = nodes.reduce(into: [any TextNode]()) { array, next in
|
self.nodes = nodes.reduce(into: [any TextNode]()) { array, next in
|
||||||
if let many = next as? NodeContainer {
|
if let many = next as? _NodeContainer {
|
||||||
array += many.nodes
|
array += many.nodes
|
||||||
} else {
|
} else {
|
||||||
array.append(next)
|
array.append(next)
|
||||||
@@ -71,3 +75,5 @@ public struct NodeContainer: TextNode {
|
|||||||
nodes.reduce("") { $0 + $1.render() }
|
nodes.reduce("") { $0 + $1.render() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:enable type_name
|
||||||
|
|||||||
30
Sources/CliDocCore/Documentation.docc/CliDocCore.md
Normal file
30
Sources/CliDocCore/Documentation.docc/CliDocCore.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# ``CliDocCore``
|
||||||
|
|
||||||
|
A framework for writing `cli` documentation in a way similar to `SwiftUI`, where
|
||||||
|
your types conform to ``TextNode`` and implement a ``TextNode/body`` that
|
||||||
|
returns a ``TextNode``, generally using the essential types described below.
|
||||||
|
|
||||||
|
## Topics
|
||||||
|
|
||||||
|
### Essentials
|
||||||
|
|
||||||
|
- ``VStack``
|
||||||
|
- ``HStack``
|
||||||
|
- ``Section``
|
||||||
|
- ``Group``
|
||||||
|
- ``Empty``
|
||||||
|
- ``AnyTextNode``
|
||||||
|
|
||||||
|
### Styling
|
||||||
|
|
||||||
|
- ``SectionStyle``
|
||||||
|
- ``DefaultSectionStyle``
|
||||||
|
- ``SectionConfiguration``
|
||||||
|
- ``TextStyleConfiguration``
|
||||||
|
|
||||||
|
### Base Protocols
|
||||||
|
|
||||||
|
- ``TextNode``
|
||||||
|
- ``TextNodeRepresentable``
|
||||||
|
- ``TextStyle``
|
||||||
|
- ``TextModifier``
|
||||||
BIN
Sources/CliDocCore/Documentation.docc/Resources/section.png
Normal file
BIN
Sources/CliDocCore/Documentation.docc/Resources/section.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
@@ -37,16 +37,11 @@
|
|||||||
///
|
///
|
||||||
/// print(mySection.render())
|
/// print(mySection.render())
|
||||||
/// ```
|
/// ```
|
||||||
/// **Note:** colored output / styling only shows in the terminal.
|
|
||||||
///
|
///
|
||||||
/// ```bash
|
/// _Below is an image of the output from the `mySection.render()` above._
|
||||||
///
|
///
|
||||||
/// Awesome
|
/// 
|
||||||
///
|
///
|
||||||
/// My super awesome section
|
|
||||||
///
|
|
||||||
/// Note: this is super awesome
|
|
||||||
/// ```
|
|
||||||
public struct Section<Header: TextNode, Content: TextNode, Footer: TextNode>: TextNode {
|
public struct Section<Header: TextNode, Content: TextNode, Footer: TextNode>: TextNode {
|
||||||
|
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
@@ -124,7 +119,8 @@ public extension Section {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds the type-erased values of a ``Section``, used to style a section.
|
/// Holds the type-erased values of a ``Section``, that can be used to create
|
||||||
|
/// custom styling for a section.
|
||||||
public struct SectionConfiguration {
|
public struct SectionConfiguration {
|
||||||
/// The type-erased header of a section.
|
/// The type-erased header of a section.
|
||||||
public let header: any TextNode
|
public let header: any TextNode
|
||||||
@@ -143,6 +139,9 @@ public struct SectionConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used to declare a custom style for a ``Section``. Your custom section style
|
||||||
|
/// must conform to this protocol.
|
||||||
|
///
|
||||||
public protocol SectionStyle: TextModifier where Content == SectionConfiguration {}
|
public protocol SectionStyle: TextModifier where Content == SectionConfiguration {}
|
||||||
|
|
||||||
public extension SectionStyle where Self == DefaultSectionStyle {
|
public extension SectionStyle where Self == DefaultSectionStyle {
|
||||||
|
|||||||
@@ -1,7 +1,23 @@
|
|||||||
|
/// A namespace for separator types that are used in text nodes.
|
||||||
|
///
|
||||||
|
/// These are generally used in the ``HStack``'s and ``VStack``'s to
|
||||||
|
/// specifiy how the nodes they contain are separated.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// **Note:**
|
||||||
|
///
|
||||||
|
/// > By default nodes do not contain any separators, unless they are written inline.
|
||||||
|
/// > However, both ``HStack`` and ``VStack`` allow you to specify the separator to use
|
||||||
|
/// > to control how the individual nodes they contain are separated.
|
||||||
|
///
|
||||||
public enum Separator {
|
public enum Separator {
|
||||||
|
|
||||||
/// Represents a horizontal separator that can be used between text nodes, typically inside
|
/// Represents a horizontal separator that can be used between text nodes, typically inside
|
||||||
/// an ``HStack``
|
/// an ``HStack``
|
||||||
|
///
|
||||||
|
/// **Note:**
|
||||||
|
/// > By default nodes do not contain any separators, unless they are written inline.
|
||||||
|
///
|
||||||
public enum Horizontal: TextNode {
|
public enum Horizontal: TextNode {
|
||||||
/// Separate nodes by spaces of the given count.
|
/// Separate nodes by spaces of the given count.
|
||||||
case space(count: Int = 1)
|
case space(count: Int = 1)
|
||||||
@@ -10,6 +26,12 @@ public enum Separator {
|
|||||||
case tab(count: Int = 1)
|
case tab(count: Int = 1)
|
||||||
|
|
||||||
/// Separate nodes by the provided string of the given count.
|
/// Separate nodes by the provided string of the given count.
|
||||||
|
///
|
||||||
|
/// **Note:**
|
||||||
|
///
|
||||||
|
/// > This can allow for non-sensical separators, so should only be used
|
||||||
|
/// > if the provided horizontal separators do not work for you.
|
||||||
|
///
|
||||||
case custom(String, count: Int = 1)
|
case custom(String, count: Int = 1)
|
||||||
|
|
||||||
@TextBuilder
|
@TextBuilder
|
||||||
@@ -28,8 +50,34 @@ public enum Separator {
|
|||||||
|
|
||||||
/// Represents a vertical separator that can be used between text nodes, typically inside
|
/// Represents a vertical separator that can be used between text nodes, typically inside
|
||||||
/// a ``VStack``
|
/// a ``VStack``
|
||||||
|
///
|
||||||
|
/// **Note:**
|
||||||
|
/// > By default nodes do not contain any separators, so if you would
|
||||||
|
/// > like a blank line separating nodes, then a count of `2` is required.
|
||||||
|
/// > A count of `1` will place nodes on the next line.
|
||||||
|
///
|
||||||
public enum Vertical: TextNode {
|
public enum Vertical: TextNode {
|
||||||
|
/// Separate nodes by new line characters of the given count.
|
||||||
|
///
|
||||||
|
/// **Note:**
|
||||||
|
/// > By default nodes do not contain any separtors, so if you would
|
||||||
|
/// > like a blank line separating nodes, then a count of `2` is required.
|
||||||
|
/// > A count of `1` will place nodes on the next line.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - count: The count of the new lines to use.
|
||||||
case newLine(count: Int = 1)
|
case newLine(count: Int = 1)
|
||||||
|
|
||||||
|
/// Separate nodes by the supplied string with the given count.
|
||||||
|
///
|
||||||
|
/// **Note:**
|
||||||
|
///
|
||||||
|
/// > This can allow for non-sensical separators, so should only be used
|
||||||
|
/// > if the provided vertical separators do not work for you.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - count: The count of the new lines to use.
|
||||||
case custom(String, count: Int = 1)
|
case custom(String, count: Int = 1)
|
||||||
|
|
||||||
@TextBuilder
|
@TextBuilder
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
/// A type that can modify a text node before it is rendered.
|
||||||
|
///
|
||||||
|
/// This allows you to create custom styles for your text-nodes.
|
||||||
|
///
|
||||||
public protocol TextModifier {
|
public protocol TextModifier {
|
||||||
// swiftlint:disable type_name
|
// swiftlint:disable type_name
|
||||||
associatedtype _Body: TextNode
|
associatedtype _Body: TextNode
|
||||||
@@ -6,6 +10,10 @@ public protocol TextModifier {
|
|||||||
|
|
||||||
associatedtype Content
|
associatedtype Content
|
||||||
|
|
||||||
|
/// Apply custom styling to the text node.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - content: The text node to be styled.
|
||||||
@TextBuilder
|
@TextBuilder
|
||||||
func render(content: Content) -> Body
|
func render(content: Content) -> Body
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
public protocol NodeRepresentable {
|
/// A type that can produce a string to be used as a documentation
|
||||||
|
/// text node.
|
||||||
|
public protocol TextNodeRepresentable {
|
||||||
|
|
||||||
|
/// Produces the string output to use as the documentation string.
|
||||||
func render() -> String
|
func render() -> String
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol TextNode: NodeRepresentable {
|
/// A type that can produce a string to be used as a documentation
|
||||||
|
/// text node.
|
||||||
|
public protocol TextNode: TextNodeRepresentable {
|
||||||
// swiftlint:disable type_name
|
// swiftlint:disable type_name
|
||||||
associatedtype _Body: TextNode
|
associatedtype _Body: TextNode
|
||||||
typealias Body = _Body
|
typealias Body = _Body
|
||||||
@@ -19,16 +25,12 @@ public extension TextNode {
|
|||||||
|
|
||||||
// MARK: - String
|
// MARK: - String
|
||||||
|
|
||||||
extension String: NodeRepresentable {
|
extension String: TextNodeRepresentable {
|
||||||
public func render() -> String {
|
public func render() -> String { self }
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension String: TextNode {
|
extension String: TextNode {
|
||||||
public var body: some TextNode {
|
public var body: some TextNode { self }
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Optional
|
// MARK: - Optional
|
||||||
@@ -45,7 +47,7 @@ extension Optional: TextNode where Wrapped: TextNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Optional: NodeRepresentable where Wrapped: NodeRepresentable, Wrapped: TextNode {
|
extension Optional: TextNodeRepresentable where Wrapped: TextNodeRepresentable, Wrapped: TextNode {
|
||||||
|
|
||||||
public func render() -> String {
|
public func render() -> String {
|
||||||
body.render()
|
body.render()
|
||||||
@@ -56,11 +58,11 @@ extension Optional: NodeRepresentable where Wrapped: NodeRepresentable, Wrapped:
|
|||||||
|
|
||||||
extension Array: TextNode where Element: TextNode {
|
extension Array: TextNode where Element: TextNode {
|
||||||
public var body: some TextNode {
|
public var body: some TextNode {
|
||||||
NodeContainer(nodes: self)
|
_NodeContainer(nodes: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Array: NodeRepresentable where Element: NodeRepresentable, Element: TextNode {
|
extension Array: TextNodeRepresentable where Element: TextNodeRepresentable, Element: TextNode {
|
||||||
public func render() -> String {
|
public func render() -> String {
|
||||||
body.render()
|
body.render()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,36 +2,68 @@ import Rainbow
|
|||||||
|
|
||||||
public extension TextNode {
|
public extension TextNode {
|
||||||
|
|
||||||
|
/// Apply coloring to a text node.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - color: The color to apply to the text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func color(_ color: NamedColor) -> some TextNode {
|
func color(_ color: NamedColor) -> some TextNode {
|
||||||
textStyle(.color(color))
|
textStyle(_ColorTextStyle(.foreground(.named(color))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apply coloring to a text node.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - bit8: The color to apply to the text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func color(_ bit8: UInt8) -> some TextNode {
|
func color(_ bit8: UInt8) -> some TextNode {
|
||||||
textStyle(.color(bit8: bit8))
|
textStyle(_ColorTextStyle(.foreground(.bit8(bit8))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apply coloring to a text node using RGB.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - red: The red color to apply to the text node.
|
||||||
|
/// - green: The green color to apply to the text node.
|
||||||
|
/// - blue: The blue color to apply to the text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func color(_ red: UInt8, _ green: UInt8, _ blue: UInt8) -> some TextNode {
|
func color(_ red: UInt8, _ green: UInt8, _ blue: UInt8) -> some TextNode {
|
||||||
textStyle(.color(rgb: (red, green, blue)))
|
textStyle(_ColorTextStyle(.foreground(.bit24((red, green, blue)))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apply background coloring to a text node.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - color: The color to apply to the text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func backgroundColor(_ name: NamedBackgroundColor) -> some TextNode {
|
func backgroundColor(_ color: NamedBackgroundColor) -> some TextNode {
|
||||||
textStyle(.backgroundColor(name))
|
textStyle(_ColorTextStyle(.background(.named(color))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apply background coloring to a text node.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - bit8: The color to apply to the text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func backgroundColor(_ bit8: UInt8) -> some TextNode {
|
func backgroundColor(_ bit8: UInt8) -> some TextNode {
|
||||||
textStyle(.backgroundColor(bit8: bit8))
|
textStyle(_ColorTextStyle(.background(.bit8(bit8))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apply background coloring to a text node using RGB.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - red: The red color to apply to the text node.
|
||||||
|
/// - green: The green color to apply to the text node.
|
||||||
|
/// - blue: The blue color to apply to the text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func backgroundColor(_ red: UInt8, _ green: UInt8, _ blue: UInt8) -> some TextNode {
|
func backgroundColor(_ red: UInt8, _ green: UInt8, _ blue: UInt8) -> some TextNode {
|
||||||
textStyle(.backgroundColor(rgb: (red, green, blue)))
|
textStyle(_ColorTextStyle(.background(.bit24((red, green, blue)))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apply styles to a text node.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - styles: The styles to apply.
|
||||||
@inlinable
|
@inlinable
|
||||||
func textStyle<S: TextStyle>(_ styles: S...) -> some TextNode {
|
func textStyle<S: TextStyle>(_ styles: S...) -> some TextNode {
|
||||||
styles.reduce(render()) { string, style in
|
styles.reduce(render()) { string, style in
|
||||||
@@ -39,28 +71,49 @@ public extension TextNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apply a bold text style to a text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func bold() -> some TextNode { textStyle(.bold) }
|
func bold() -> some TextNode { textStyle(.bold) }
|
||||||
|
|
||||||
|
/// Apply a dim text style to a text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func dim() -> some TextNode { textStyle(.dim) }
|
func dim() -> some TextNode { textStyle(.dim) }
|
||||||
|
|
||||||
|
/// Apply an italic text style to a text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func italic() -> some TextNode { textStyle(.italic) }
|
func italic() -> some TextNode { textStyle(.italic) }
|
||||||
|
|
||||||
|
/// Apply an underline text style to a text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func underline() -> some TextNode { textStyle(.underline) }
|
func underline() -> some TextNode { textStyle(.underline) }
|
||||||
|
|
||||||
|
/// Apply a blink text style to a text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func blink() -> some TextNode { textStyle(.blink) }
|
func blink() -> some TextNode { textStyle(.blink) }
|
||||||
|
|
||||||
|
/// Apply a strike-through text style to a text node.
|
||||||
@inlinable
|
@inlinable
|
||||||
func strikeThrough() -> some TextNode { textStyle(.strikeThrough) }
|
func strikeThrough() -> some TextNode { textStyle(.strikeThrough) }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A general purpose way of styling a text node.
|
||||||
|
///
|
||||||
|
/// This is generally used for applying styling that can work with any text node.
|
||||||
|
///
|
||||||
|
/// Most of the time you will want to customize styles for a text node's type instead
|
||||||
|
/// of using this.
|
||||||
public protocol TextStyle: TextModifier where Content == TextStyleConfiguration {}
|
public protocol TextStyle: TextModifier where Content == TextStyleConfiguration {}
|
||||||
|
|
||||||
|
/// A type-erased text node that can be used for creating
|
||||||
|
/// custom styles.
|
||||||
|
///
|
||||||
|
/// This is generally used to change the style of text nodes as
|
||||||
|
/// a whole, such as applying text colors or styling such as `bold`.
|
||||||
|
///
|
||||||
|
/// Most of the time you will want to customize styles for a text node's
|
||||||
|
/// type, instead of using this.
|
||||||
|
///
|
||||||
public struct TextStyleConfiguration {
|
public struct TextStyleConfiguration {
|
||||||
public let node: any TextNode
|
public let node: any TextNode
|
||||||
|
|
||||||
@@ -70,7 +123,7 @@ public struct TextStyleConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension TextStyle where Self == StyledText {
|
public extension TextStyle where Self == _StyledText {
|
||||||
|
|
||||||
@inlinable
|
@inlinable
|
||||||
static var bold: Self { .init(.bold) }
|
static var bold: Self { .init(.bold) }
|
||||||
@@ -91,40 +144,8 @@ public extension TextStyle where Self == StyledText {
|
|||||||
static var strikeThrough: Self { .init(.strikethrough) }
|
static var strikeThrough: Self { .init(.strikethrough) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension TextStyle where Self == ColorTextStyle {
|
// swiftlint:disable type_name
|
||||||
|
public struct _ColorTextStyle: TextStyle {
|
||||||
@inlinable
|
|
||||||
static func color(_ name: NamedColor) -> Self {
|
|
||||||
.init(.foreground(.named(name)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@inlinable
|
|
||||||
static func color(bit8: UInt8) -> Self {
|
|
||||||
.init(.foreground(.bit8(bit8)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@inlinable
|
|
||||||
static func color(rgb: RGB) -> Self {
|
|
||||||
.init(.foreground(.bit24(rgb)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@inlinable
|
|
||||||
static func backgroundColor(_ name: NamedBackgroundColor) -> Self {
|
|
||||||
.init(.background(.named(name)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@inlinable
|
|
||||||
static func backgroundColor(bit8: UInt8) -> Self {
|
|
||||||
.init(.background(.bit8(bit8)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@inlinable
|
|
||||||
static func backgroundColor(rgb: RGB) -> Self {
|
|
||||||
.init(.background(.bit24(rgb)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct ColorTextStyle: TextStyle {
|
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
enum Style {
|
enum Style {
|
||||||
case foreground(ColorType)
|
case foreground(ColorType)
|
||||||
@@ -150,7 +171,7 @@ public struct ColorTextStyle: TextStyle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct StyledText: TextStyle {
|
public struct _StyledText: TextStyle {
|
||||||
@usableFromInline
|
@usableFromInline
|
||||||
let style: Style
|
let style: Style
|
||||||
|
|
||||||
@@ -164,3 +185,5 @@ public struct StyledText: TextStyle {
|
|||||||
content.node.render().applyingStyle(style)
|
content.node.render().applyingStyle(style)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swiftlint:enable type_name
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@usableFromInline
|
@usableFromInline
|
||||||
func array(from node: any TextNode) -> [any TextNode] {
|
func array(from node: any TextNode) -> [any TextNode] {
|
||||||
if let container = node as? NodeContainer {
|
if let container = node as? _NodeContainer {
|
||||||
return container.nodes
|
return container.nodes
|
||||||
} else if let array = node as? [any TextNode] {
|
} else if let array = node as? [any TextNode] {
|
||||||
return array
|
return array
|
||||||
|
|||||||
Reference in New Issue
Block a user