feat: Adds section and section style, needs tests
This commit is contained in:
1
.nvim/xcodebuild/coverage.json
Normal file
1
.nvim/xcodebuild/coverage.json
Normal file
File diff suppressed because one or more lines are too long
1
.nvim/xcodebuild/devices.json
Normal file
1
.nvim/xcodebuild/devices.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"projectFile": "/Volumes/Bucket/Repos/swift-cli-doc/Package.swift", "scheme": "swift-cli-doc", "devices": [{"platform": "macOS", "name": "My Mac", "arch": "arm64e", "id": "00008103-000E79D011EA001E"}]}
|
||||||
1
.nvim/xcodebuild/report.json
Normal file
1
.nvim/xcodebuild/report.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"testsCount": 6, "xcresultFilepath": "/Users/michael/Library/Developer/Xcode/DerivedData/swift-cli-doc-dgihrbuebwxquzdknevkczbenunz/Logs/Test/Test-swift-cli-doc-2024.12.04_17-02-40--0500.xcresult", "failedTestsCount": 0, "tests": {"CliDocTests:_Global": [{"target": "CliDocTests", "name": "testGroup", "testResult": "passed", "swiftTestingId": "CliDocTests/testGroup", "class": "_Global", "time": "0.00031 seconds", "success": true}, {"target": "CliDocTests", "name": "testHStack", "testResult": "passed", "swiftTestingId": "CliDocTests/testHStack", "class": "_Global", "time": "0.000081 seconds", "success": true}, {"target": "CliDocTests", "name": "testVStack", "testResult": "passed", "swiftTestingId": "CliDocTests/testVStack", "class": "_Global", "time": "0.000049 seconds", "success": true}, {"target": "CliDocTests", "name": "testNote", "testResult": "passed", "swiftTestingId": "CliDocTests/testNote", "class": "_Global", "time": "0.00027 seconds", "success": true}, {"target": "CliDocTests", "name": "testExamples", "testResult": "passed", "swiftTestingId": "CliDocTests/testExamples", "class": "_Global", "time": "0.00027 seconds", "success": true}, {"target": "CliDocTests", "name": "testExamplesWithCustomExampleOnlyStyle", "testResult": "passed", "swiftTestingId": "CliDocTests/testExamplesWithCustomExampleOnlyStyle", "class": "_Global", "time": "0.00016 seconds", "success": true}]}, "buildWarnings": [], "usesSwiftTesting": true, "testErrors": [], "buildErrors": []}
|
||||||
1
.nvim/xcodebuild/settings.json
Normal file
1
.nvim/xcodebuild/settings.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"platform": "macOS", "workingDirectory": "/Volumes/Bucket/Repos/swift-cli-doc", "swiftPackage": "/Volumes/Bucket/Repos/swift-cli-doc/Package.swift", "deviceName": "My Mac", "destination": "00008103-000E79D011EA001E", "lastBuildTime": 7, "scheme": "swift-cli-doc"}
|
||||||
1
.nvim/xcodebuild/test-explorer.json
Normal file
1
.nvim/xcodebuild/test-explorer.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[{"status": "passed", "hidden": false, "name": "CliDocTests", "classes": [{"status": "passed", "hidden": false, "id": "CliDocTests/_Global", "name": "_Global", "tests": [{"status": "passed", "hidden": false, "name": "testExamples", "id": "CliDocTests/_Global/testExamples", "swiftTestingId": "CliDocTests/testExamples", "kind": "test"}, {"status": "passed", "hidden": false, "name": "testExamplesWithCustomExampleOnlyStyle", "id": "CliDocTests/_Global/testExamplesWithCustomExampleOnlyStyle", "swiftTestingId": "CliDocTests/testExamplesWithCustomExampleOnlyStyle", "kind": "test"}, {"status": "passed", "hidden": false, "name": "testGroup", "id": "CliDocTests/_Global/testGroup", "swiftTestingId": "CliDocTests/testGroup", "kind": "test"}, {"status": "passed", "hidden": false, "name": "testHStack", "id": "CliDocTests/_Global/testHStack", "swiftTestingId": "CliDocTests/testHStack", "kind": "test"}, {"status": "passed", "hidden": false, "name": "testNote", "id": "CliDocTests/_Global/testNote", "swiftTestingId": "CliDocTests/testNote", "kind": "test"}, {"status": "passed", "hidden": false, "name": "testVStack", "id": "CliDocTests/_Global/testVStack", "swiftTestingId": "CliDocTests/testVStack", "kind": "test"}], "swiftTestingId": "CliDocTests", "kind": "class"}], "id": "CliDocTests", "kind": "target"}]
|
||||||
@@ -11,7 +11,7 @@ public extension ExampleSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func exampleStyle<S: ExampleStyle>(_ style: S) -> some TextNode {
|
func exampleStyle<S: ExampleStyle>(_ style: S) -> some TextNode {
|
||||||
DefaultExamplesStyle().render(content: .init(
|
DefaultExamplesStyle(exampleStyle: style).render(content: .init(
|
||||||
header: header,
|
header: header,
|
||||||
label: label,
|
label: label,
|
||||||
examples: examples
|
examples: examples
|
||||||
|
|||||||
37
Sources/CliDoc/Modifiers/SectionStyle.swift
Normal file
37
Sources/CliDoc/Modifiers/SectionStyle.swift
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
public extension Section {
|
||||||
|
|
||||||
|
@inlinable
|
||||||
|
func style<S: SectionStyle>(_ style: S) -> some TextNode {
|
||||||
|
style.render(content: .init(header: header, content: content, footer: footer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct SectionConfiguration {
|
||||||
|
public let header: any TextNode
|
||||||
|
public let content: any TextNode
|
||||||
|
public let footer: any TextNode
|
||||||
|
|
||||||
|
@usableFromInline
|
||||||
|
init(header: any TextNode, content: any TextNode, footer: any TextNode) {
|
||||||
|
self.header = header
|
||||||
|
self.content = content
|
||||||
|
self.footer = footer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public protocol SectionStyle: NodeModifier where Content == SectionConfiguration {}
|
||||||
|
|
||||||
|
public extension SectionStyle where Self == DefaultSectionStyle {
|
||||||
|
static var `default`: Self { DefaultSectionStyle() }
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct DefaultSectionStyle: SectionStyle {
|
||||||
|
|
||||||
|
public func render(content: SectionConfiguration) -> some TextNode {
|
||||||
|
VStack {
|
||||||
|
content.header
|
||||||
|
content.content
|
||||||
|
content.footer.textStyle(.italic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
Sources/CliDoc/Nodes/Section.swift
Normal file
46
Sources/CliDoc/Nodes/Section.swift
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
public struct Section<Header: TextNode, Content: TextNode, Footer: TextNode>: TextNode {
|
||||||
|
|
||||||
|
@usableFromInline
|
||||||
|
let header: Header
|
||||||
|
|
||||||
|
@usableFromInline
|
||||||
|
let content: Content
|
||||||
|
|
||||||
|
@usableFromInline
|
||||||
|
let footer: Footer
|
||||||
|
|
||||||
|
@inlinable
|
||||||
|
public init(
|
||||||
|
@TextBuilder header: () -> Header,
|
||||||
|
@TextBuilder content: () -> Content,
|
||||||
|
@TextBuilder footer: () -> Footer
|
||||||
|
) {
|
||||||
|
self.header = header()
|
||||||
|
self.content = content()
|
||||||
|
self.footer = footer()
|
||||||
|
}
|
||||||
|
|
||||||
|
public var body: some TextNode {
|
||||||
|
style(.default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension Section where Footer == Empty {
|
||||||
|
@inlinable
|
||||||
|
init(
|
||||||
|
@TextBuilder header: () -> Header,
|
||||||
|
@TextBuilder content: () -> Content
|
||||||
|
) {
|
||||||
|
self.init(header: header, content: content) { Empty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension Section where Header == Empty {
|
||||||
|
@inlinable
|
||||||
|
init(
|
||||||
|
@TextBuilder content: () -> Content,
|
||||||
|
@TextBuilder footer: () -> Footer
|
||||||
|
) {
|
||||||
|
self.init(header: { Empty() }, content: content, footer: footer)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user