From 65305620ae80f5aba2ece49a5965b1b19bbcf7a4 Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Thu, 9 Sep 2021 15:36:27 -0600 Subject: [PATCH 01/22] [skip ci] new-docs - Add video to readme - TT --- README.md | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d6e89e2f9..dbb600e0a 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,10 @@ SwiftCurrent is a library that lets you easily manage journeys through your Swift application. -When Developing in UIKit, each view controller has to know about the one following it in order to share data. Now imagine a flow where the first 3 screens are optional. What would it look like if you could decouple all of that? +It comes with built-in support for UIKit and SwiftUI app-routing. In SwiftCurrent workflows are a sequence of operations. Those operations are normally showing views in an application. The workflow describes the sequence of views and manages what view should come next. Your views are responsible for performing necessary tasks before proceeding forward in the workflow, like processing user input. + + -```swift -let workflow = Workflow(LocationsViewController.self) // Skip this if you have GPS - .thenProceed(with: PickupOrDeliveryViewController.self) // Skip this if you only have 1 choice - .thenProceed(with: MenuSelectionViewController.self) // Skip this for new stores - .thenProceed(with: FoodSelectionViewController.self) - .thenProceed(with: ReviewOrderViewController.self) // This lets you edit anything you've already picked - .thenProceed(with: SubmitPaymentViewController.self) - -// from wherever this flow is launched -launchInto(workflow) -``` The above code is all that is needed from the screen starting this flow. Each screen determines if it needs to show based on data passed in and what that screen knows about the system (such as GPS availability), and all of it is type safe. If you ever want to re-order these, simply move their position in the chain. As you continue to develop your applications, each view controller will become more decoupled from the rest of the app. That means, if you want a completely different order of screens, just define a new [Workflow](https://wwt.github.io/SwiftCurrent/Classes/Workflow.html). From ef5252495b13bd6f10f24b93b284c81de259a651 Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Thu, 9 Sep 2021 15:39:38 -0600 Subject: [PATCH 02/22] [skip ci] new-docs - Use the HTML5 video tag instead - TT --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dbb600e0a..9e8cefc7a 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,10 @@ SwiftCurrent is a library that lets you easily manage journeys through your Swif It comes with built-in support for UIKit and SwiftUI app-routing. In SwiftCurrent workflows are a sequence of operations. Those operations are normally showing views in an application. The workflow describes the sequence of views and manages what view should come next. Your views are responsible for performing necessary tasks before proceeding forward in the workflow, like processing user input. - + The above code is all that is needed from the screen starting this flow. Each screen determines if it needs to show based on data passed in and what that screen knows about the system (such as GPS availability), and all of it is type safe. If you ever want to re-order these, simply move their position in the chain. From fe13f11e959c4dea0cd7d610f53fdc7d72e00d2f Mon Sep 17 00:00:00 2001 From: Tyler Thompson <33705774+Tyler-Keith-Thompson@users.noreply.github.com> Date: Thu, 9 Sep 2021 15:56:20 -0600 Subject: [PATCH 03/22] Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9e8cefc7a..8564e2989 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,11 @@ SwiftCurrent is a library that lets you easily manage journeys through your Swif It comes with built-in support for UIKit and SwiftUI app-routing. In SwiftCurrent workflows are a sequence of operations. Those operations are normally showing views in an application. The workflow describes the sequence of views and manages what view should come next. Your views are responsible for performing necessary tasks before proceeding forward in the workflow, like processing user input. - + + +https://user-images.githubusercontent.com/33705774/132767762-7447753c-feba-4ef4-b54c-38bfe9d1ee82.mp4 + + The above code is all that is needed from the screen starting this flow. Each screen determines if it needs to show based on data passed in and what that screen knows about the system (such as GPS availability), and all of it is type safe. If you ever want to re-order these, simply move their position in the chain. From 055989ea0b588f04ca68f9bd072839372da8946a Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Thu, 9 Sep 2021 15:58:39 -0600 Subject: [PATCH 04/22] [skip ci] new-docs - Get rid of old text - TT --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index 8564e2989..79237d74c 100644 --- a/README.md +++ b/README.md @@ -15,16 +15,8 @@ SwiftCurrent is a library that lets you easily manage journeys through your Swif It comes with built-in support for UIKit and SwiftUI app-routing. In SwiftCurrent workflows are a sequence of operations. Those operations are normally showing views in an application. The workflow describes the sequence of views and manages what view should come next. Your views are responsible for performing necessary tasks before proceeding forward in the workflow, like processing user input. - - https://user-images.githubusercontent.com/33705774/132767762-7447753c-feba-4ef4-b54c-38bfe9d1ee82.mp4 - - -The above code is all that is needed from the screen starting this flow. Each screen determines if it needs to show based on data passed in and what that screen knows about the system (such as GPS availability), and all of it is type safe. If you ever want to re-order these, simply move their position in the chain. - -As you continue to develop your applications, each view controller will become more decoupled from the rest of the app. That means, if you want a completely different order of screens, just define a new [Workflow](https://wwt.github.io/SwiftCurrent/Classes/Workflow.html). - ## See it in action with our example app Clone our repo, open `SwiftCurrent.xcworkspace`, target the `UIKitExample` scheme, and run to see our example app in action. From b960babfd3694671aca312a209e63143ce7ed1e2 Mon Sep 17 00:00:00 2001 From: Tyler Thompson <33705774+Tyler-Keith-Thompson@users.noreply.github.com> Date: Thu, 9 Sep 2021 16:47:53 -0600 Subject: [PATCH 05/22] [ci skip] wip - updated the README Co-authored-by: Richard Gist --- README.md | 68 +++++++++++-------------------------------------------- 1 file changed, 13 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 79237d74c..baa46415b 100644 --- a/README.md +++ b/README.md @@ -17,64 +17,24 @@ It comes with built-in support for UIKit and SwiftUI app-routing. In SwiftCurren https://user-images.githubusercontent.com/33705774/132767762-7447753c-feba-4ef4-b54c-38bfe9d1ee82.mp4 -## See it in action with our example app +### Why should I use SwiftCurrent? +Architectural patterns and libraries that attempt to create a separation between views and workflows already exist. However, SwiftCurrent is different. We took a new design approach that focuses on -Clone our repo, open `SwiftCurrent.xcworkspace`, target the `UIKitExample` scheme, and run to see our example app in action. +- **A Developer Friendly API**: The library was built with developers in mind. It started with a group of developers talking about the code experience they desired. Then the library team took on whatever complexities were necessary to bring them that experience. +- **Compile-time safety**: We tell you at compile time everything we can so you know things will work. +- **Minimal Boilerplate**: We have hidden this as much as possible. We hate it as much as you do and are constantly working on cutting the cruft. -The [example app has a README](https://github.com/wwt/SwiftCurrent/blob/main/ExampleApps/UIKitExample/README.md) that details interesting usages. - -## Interested but you need SwiftUI support? - -[We're working on it now!](https://github.com/wwt/SwiftCurrent/milestone/2) - -If you would like to try the beta release, please install the `BETA_SwiftCurrent_SwiftUI` product in SPM or the `BETA_SwiftUI` sub spec in CocoaPods. For more detailed steps, [see our installation instructions](https://wwt.github.io/SwiftCurrent/installation.html). See [Getting Started with SwiftUI](https://wwt.github.io/SwiftCurrent/getting-started-with-swiftui.html) for a quick tutorial. To see the example app for SwiftUI, clone our repo, open `SwiftCurrent.xcworkspace`, target the `SwiftUIExample` scheme, and run. The [example app has a README](https://github.com/wwt/SwiftCurrent/blob/main/ExampleApps/SwiftUIExample/README.md) that details interesting usages. - -In order to use the library with SwiftUI, your minimum targeted versions must meet: iOS 14.0, macOS 11, tvOS 14.0, or watchOS 7.0. - -For us, beta means that the API may change without warning until the full release. However, we expect bugs to be at a minimum and documentation to be true and accurate. +#### From there, we created a library that: +- **Isolates your views**: You can design your views so that they are unaware of the view that will come next. +- **Easily reorders views**: Changing view order is as easy as ⌘+⌥+\[ (moving the line up or down) +- **Composes workflows together**: Create branching flows easily by joining workflows together. +- **Creates conditional flows**: Make your flows robust and handle ever-changing designs. Need a screen only to show up sometimes? Need a flow for person A and another for person B? We've got you covered. # Quick Start This quick start uses SPM, but for other approaches, [see our installation instructions](https://wwt.github.io/SwiftCurrent/installation.html). -## UIKit - -```swift -.package(url: "https://github.com/wwt/SwiftCurrent.git", .upToNextMajor(from: "4.0.0")), -... -.product(name: "SwiftCurrent", package: "SwiftCurrent"), -.product(name: "SwiftCurrent_UIKit", package: "SwiftCurrent") -``` -Then make your first FlowRepresentable view controllers: -```swift -import SwiftCurrent -import SwiftCurrent_UIKit -class OptionalViewController: UIWorkflowItem, FlowRepresentable { - let input: String - required init(with args: String) { - input = args - super.init(nibName: nil, bundle: nil) - } - required init?(coder: NSCoder) { nil } - override func viewDidLoad() { view.backgroundColor = .blue } - func shouldLoad() -> Bool { input.isEmpty } -} -class ExampleViewController: UIWorkflowItem, FlowRepresentable { - override func viewDidLoad() { view.backgroundColor = .green } -} -``` -Then from your root view controller, call: -```swift -import SwiftCurrent -... -let workflow = Workflow(OptionalViewController.self) - .thenProceed(with: ExampleViewController.self) -launchInto(workflow, args: "Skip optional screen") -``` - -And just like that you're started! - -## [BETA] SwiftUI +## SwiftUI ```swift .package(url: "https://github.com/wwt/SwiftCurrent.git", .upToNextMajor(from: "4.1.0")), @@ -110,10 +70,8 @@ WorkflowLauncher(isLaunched: .constant(true), startingArgs: "Skip optional scree And just like that you're started! -Here's an example of an app written with SwiftCurrent running wherever SwiftUI runs. Check it out: - -https://user-images.githubusercontent.com/79471462/131555558-9e01e753-cafd-4ae2-af1b-b71a1aabb71f.mp4 - +### [Check out our example apps](https://github.com/wwt/SwiftCurrent/tree/main/ExampleApps) +We have example apps for both SwiftUI and UIKit that show SwiftCurrent in action. They're even tested so you can see what it's like to test SwiftCurrent code. To run it locally, start by cloning the repo, open `SwiftCurrent.xcworkspace` and then run the `SwiftUIExample` scheme or the `UIKitExample` scheme. # Deep Dive From c4d87907d6b0336fbfa4c84e6a576382bead07e9 Mon Sep 17 00:00:00 2001 From: Tyler Thompson <33705774+Tyler-Keith-Thompson@users.noreply.github.com> Date: Thu, 9 Sep 2021 17:01:12 -0600 Subject: [PATCH 06/22] [ci skip] wip - Modified the quickstart Co-authored-by: Richard Gist --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index baa46415b..905bff7b3 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,7 @@ Architectural patterns and libraries that attempt to create a separation between - **Creates conditional flows**: Make your flows robust and handle ever-changing designs. Need a screen only to show up sometimes? Need a flow for person A and another for person B? We've got you covered. # Quick Start - -This quick start uses SPM, but for other approaches, [see our installation instructions](https://wwt.github.io/SwiftCurrent/installation.html). - -## SwiftUI +Why show a quick start when we have an example app? Because it's so easy to get started, we can just drop in 2 code snippets and you're ready to go! This quick start uses Swift Package Manager and SwiftUI, but for other approaches, [see our installation instructions](https://wwt.github.io/SwiftCurrent/installation.html). ```swift .package(url: "https://github.com/wwt/SwiftCurrent.git", .upToNextMajor(from: "4.1.0")), @@ -45,6 +42,7 @@ This quick start uses SPM, but for other approaches, [see our installation instr Then make your first FlowRepresentable view: ```swift import SwiftCurrent +import SwiftUI struct OptionalView: View, FlowRepresentable { weak var _workflowPointer: AnyFlowRepresentable? let input: String @@ -52,25 +50,28 @@ struct OptionalView: View, FlowRepresentable { var body: some View { Text("Only shows up if no input") } func shouldLoad() -> Bool { input.isEmpty } } -struct ExampleView: View, FlowRepresentable { +struct ExampleView: View, PassthroughFlowRepresentable { weak var _workflowPointer: AnyFlowRepresentable? var body: some View { Text("This is ExampleView!") } } ``` -Then from your ContentView body, add: +Then from your `ContentView` or whatever view (or app) you'd like to contain the workflow, add the following view to the body: ```swift import SwiftCurrent_SwiftUI -... -WorkflowLauncher(isLaunched: .constant(true), startingArgs: "Skip optional screen") { - thenProceed(with: OptionalView.self) { - thenProceed(with: ExampleView.self) +// ... +var body: some View { + // ... other view code (if any) + WorkflowLauncher(isLaunched: .constant(true), startingArgs: "Skip optional screen") { + thenProceed(with: OptionalView.self) { + thenProceed(with: ExampleView.self) + } } } ``` -And just like that you're started! +And just like that you've got a workflow! You can now add more items to it, or re-order the items that are there. To understand more of how this works and what is there [check out our developer docs](https://wwt.github.io/SwiftCurrent/How%20to%20use%20SwiftCurrent%20with%20SwiftUI.html) -### [Check out our example apps](https://github.com/wwt/SwiftCurrent/tree/main/ExampleApps) +# [Check out our example apps](https://github.com/wwt/SwiftCurrent/tree/main/ExampleApps) We have example apps for both SwiftUI and UIKit that show SwiftCurrent in action. They're even tested so you can see what it's like to test SwiftCurrent code. To run it locally, start by cloning the repo, open `SwiftCurrent.xcworkspace` and then run the `SwiftUIExample` scheme or the `UIKitExample` scheme. # Deep Dive From 2eef23ead12d2aabca88c66665a54db6709bf012 Mon Sep 17 00:00:00 2001 From: Tyler Thompson <33705774+Tyler-Keith-Thompson@users.noreply.github.com> Date: Thu, 9 Sep 2021 17:22:43 -0600 Subject: [PATCH 07/22] [ci skip] wip - Call to action is more apparent and guides you to the github.io page Co-authored-by: Richard Gist --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 905bff7b3..e410ad4a6 100644 --- a/README.md +++ b/README.md @@ -71,16 +71,16 @@ var body: some View { And just like that you've got a workflow! You can now add more items to it, or re-order the items that are there. To understand more of how this works and what is there [check out our developer docs](https://wwt.github.io/SwiftCurrent/How%20to%20use%20SwiftCurrent%20with%20SwiftUI.html) -# [Check out our example apps](https://github.com/wwt/SwiftCurrent/tree/main/ExampleApps) -We have example apps for both SwiftUI and UIKit that show SwiftCurrent in action. They're even tested so you can see what it's like to test SwiftCurrent code. To run it locally, start by cloning the repo, open `SwiftCurrent.xcworkspace` and then run the `SwiftUIExample` scheme or the `UIKitExample` scheme. - -# Deep Dive +# Check out our example apps +We have [example apps](https://github.com/wwt/SwiftCurrent/tree/main/ExampleApps) for both SwiftUI and UIKit that show SwiftCurrent in action. They're even tested so you can see what it's like to test SwiftCurrent code. To run it locally, start by cloning the repo, open `SwiftCurrent.xcworkspace` and then run the `SwiftUIExample` scheme or the `UIKitExample` scheme. +# [See this to learn more](https://wwt.github.io/SwiftCurrent/index.html) +For specific documentation check out: - [Why SwiftCurrent?](https://wwt.github.io/SwiftCurrent/why-this-library.html) - [Installation](https://wwt.github.io/SwiftCurrent/installation.html) +- [Getting Started with SwiftUI](https://wwt.github.io/SwiftCurrent/getting-started-with-swiftui.html) - [Getting Started with Storyboards](https://wwt.github.io/SwiftCurrent/using-storyboards.html) - [Getting Started with Programmatic UIKit Views](https://wwt.github.io/SwiftCurrent/using-programmatic-views.html) -- [[BETA] Getting Started with SwiftUI](https://wwt.github.io/SwiftCurrent/getting-started-with-swiftui.html) - [Developer Documentation](https://wwt.github.io/SwiftCurrent/index.html) - [Upgrade Path](https://github.com/wwt/SwiftCurrent/blob/main/.github/UPGRADE_PATH.md) - [Contributing to SwiftCurrent](https://github.com/wwt/SwiftCurrent/blob/main/.github/CONTRIBUTING.md) From b22c74b86a5b5f25733200c74af57e0e6ad39e8a Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 10:57:13 -0600 Subject: [PATCH 08/22] [new-docs] - Added a post processor for modifying jazzy docs as we might desire - TT --- .github/DocsPostProcessor/.gitignore | 7 +++ .github/DocsPostProcessor/Package.swift | 25 ++++++++++ .../DocsPostProcessor/DocsPostProcessor.swift | 48 +++++++++++++++++++ .../Sources/DocsPostProcessor/main.swift | 1 + 4 files changed, 81 insertions(+) create mode 100644 .github/DocsPostProcessor/.gitignore create mode 100644 .github/DocsPostProcessor/Package.swift create mode 100644 .github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift create mode 100644 .github/DocsPostProcessor/Sources/DocsPostProcessor/main.swift diff --git a/.github/DocsPostProcessor/.gitignore b/.github/DocsPostProcessor/.gitignore new file mode 100644 index 000000000..bb460e7be --- /dev/null +++ b/.github/DocsPostProcessor/.gitignore @@ -0,0 +1,7 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata diff --git a/.github/DocsPostProcessor/Package.swift b/.github/DocsPostProcessor/Package.swift new file mode 100644 index 000000000..1f1f7b94b --- /dev/null +++ b/.github/DocsPostProcessor/Package.swift @@ -0,0 +1,25 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "DocsPostProcessor", + products: [ + .executable( + name: "DocsPostProcessor", + targets: ["DocsPostProcessor"]), + ], + dependencies: [ + .package(url: "https://github.com/scinfu/SwiftSoup.git", from: "1.7.4"), + .package(url: "https://github.com/apple/swift-argument-parser", from: "0.5.0"), + ], + targets: [ + .executableTarget( + name: "DocsPostProcessor", + dependencies: [ + "SwiftSoup", + .product(name: "ArgumentParser", package: "swift-argument-parser"), + ]), + ] +) diff --git a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift new file mode 100644 index 000000000..2008ea422 --- /dev/null +++ b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift @@ -0,0 +1,48 @@ +import Foundation +import ArgumentParser +import SwiftSoup + +struct DocsPostProcessor: ParsableCommand { + enum Err: Error { + case noOverviewFound + } + + @Flag(help: "Replaces overview in the left navigation with rendered README") + var replaceOverviewWithReadme = false + + @Argument(help: "The file, or directory with the HTML to change") + var path: String + + mutating func run() throws { + let url = URL(fileURLWithPath: FileManager.default.currentDirectoryPath).appendingPathComponent(path) + var files: [URL] = (url.pathExtension == "html") ? [url] : [] + if url.pathExtension != "html", let enumerator = FileManager.default.enumerator(at: url, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles]) { + for case let fileURL as URL in enumerator { + let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey]) + if fileAttributes.isRegularFile == true, fileURL.pathExtension == "html" { + files.append(fileURL) + } + } + } + for file in files { + let html = try String(contentsOf: file, encoding: .utf8) + let doc: Document = try SwiftSoup.parse(html) + if replaceOverviewWithReadme { + print("Replacing overview with README for: \(file.absoluteString)") + try replaceOverviewWithReadme(document: doc) + } + try doc.html().write(to: file, atomically: true, encoding: .utf8) + } + } + + func replaceOverviewWithReadme(document: Document) throws { + if let nav = try? document.select("nav").first() { + if let firstNavLink = try nav.getElementsByClass("nav-group-name-link").first(), + URL(fileURLWithPath: try firstNavLink.attr("href")).lastPathComponent == "Overview.html" { + try firstNavLink.attr("href", "index.html") + } else { + throw Err.noOverviewFound + } + } + } +} diff --git a/.github/DocsPostProcessor/Sources/DocsPostProcessor/main.swift b/.github/DocsPostProcessor/Sources/DocsPostProcessor/main.swift new file mode 100644 index 000000000..6ea97496b --- /dev/null +++ b/.github/DocsPostProcessor/Sources/DocsPostProcessor/main.swift @@ -0,0 +1 @@ +DocsPostProcessor.main() \ No newline at end of file From 104754778bba747e489b96e50a14dda638c24147 Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 11:08:53 -0600 Subject: [PATCH 09/22] [new-docs] - Replace readme video with vimeo embed - TT --- .../DocsPostProcessor/DocsPostProcessor.swift | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift index 2008ea422..c0fb4b9e1 100644 --- a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift +++ b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift @@ -10,6 +10,9 @@ struct DocsPostProcessor: ParsableCommand { @Flag(help: "Replaces overview in the left navigation with rendered README") var replaceOverviewWithReadme = false + @Flag(help: "Replaces readme video link with an embedded vimeo player") + var replaceReadmeVideoWithVimeoEmbed = false + @Argument(help: "The file, or directory with the HTML to change") var path: String @@ -28,8 +31,12 @@ struct DocsPostProcessor: ParsableCommand { let html = try String(contentsOf: file, encoding: .utf8) let doc: Document = try SwiftSoup.parse(html) if replaceOverviewWithReadme { - print("Replacing overview with README for: \(file.absoluteString)") try replaceOverviewWithReadme(document: doc) + print("Replaced overview with README for: \(file.absoluteString)") + } + if replaceReadmeVideoWithVimeoEmbed, file.lastPathComponent == "index.html" { + try replaceReadmeVideoWithVimeoEmbed(document: doc) + print("Replaced readme video with vimeo embed") } try doc.html().write(to: file, atomically: true, encoding: .utf8) } @@ -45,4 +52,13 @@ struct DocsPostProcessor: ParsableCommand { } } } + + func replaceReadmeVideoWithVimeoEmbed(document: Document) throws { + if let article = try? document.select("article").first() { + let link = try article.getElementsByAttributeValue("href", "https://user-images.githubusercontent.com/33705774/132767762-7447753c-feba-4ef4-b54c-38bfe9d1ee82.mp4") + try link.wrap(""" + + """) + } + } } From 979bf719765e680d962fcb677505304cc07b5d86 Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 11:15:39 -0600 Subject: [PATCH 10/22] [new-docs] - Docs are absolutely beautiful! - TT --- .../Sources/DocsPostProcessor/DocsPostProcessor.swift | 2 +- .github/document.sh | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift index c0fb4b9e1..7fee7b192 100644 --- a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift +++ b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift @@ -57,7 +57,7 @@ struct DocsPostProcessor: ParsableCommand { if let article = try? document.select("article").first() { let link = try article.getElementsByAttributeValue("href", "https://user-images.githubusercontent.com/33705774/132767762-7447753c-feba-4ef4-b54c-38bfe9d1ee82.mp4") try link.wrap(""" - +
""") } } diff --git a/.github/document.sh b/.github/document.sh index 5ca821283..bb7a26712 100755 --- a/.github/document.sh +++ b/.github/document.sh @@ -6,4 +6,6 @@ jazzy --config .github/.jazzy.yaml --podspec SwiftCurrent.podspec --sourcekitten rm swiftcurrent-docs.json rm swiftcurrentuikit-docs.json rm swiftcurrent-swiftui-docs.json -open docs/index.html \ No newline at end of file +cd .github/DocsPostProcessor +swift run DocsPostProcessor ../../Docs --replace-overview-with-readme --replace-readme-video-with-vimeo-embed +open ../../docs/index.html \ No newline at end of file From eb860ff5cb43be9f05bdb7dd5acdbf7e2f8abe83 Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 11:48:54 -0600 Subject: [PATCH 11/22] [new-docs] - Added an abstract for creating workflows - TT --- .github/abstract/Creating Workflows.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/abstract/Creating Workflows.md diff --git a/.github/abstract/Creating Workflows.md b/.github/abstract/Creating Workflows.md new file mode 100644 index 000000000..967ef413c --- /dev/null +++ b/.github/abstract/Creating Workflows.md @@ -0,0 +1,8 @@ +### What is a workflow? +A `workflow` is a description for a sequence of `FlowRepresentable`. Those operations are normally displaying screens or views. There are different ways of [creating workflows in SwiftUI](Creating%20Workflows%20in%20SwiftUI.html) and [creating workflows in UIKit](Creating%20Workflows%20in%20UIKit.html). + +### What is a `FlowRepresentable`? +A `FlowRepresentable` is a protocol that describes a type that can appear in a `workflow`. It optionally declares `FlowRepresentable.WorkflowInput` and `FlowRepresentable.WorkflowOutput` indicating whether it requires data or whether it passes data forward. It also provides an initializer so that it can be created by the `workflow`. Once an item conforms to `FlowRepresentable` it is capable of being injected into any `workflow`. + +### Valid workflow sequences +Workflows enforce (either at compile-time or run-time) that the sequence of `FlowRepresentables` are well-formed. For example if a particular `FlowRepresentable` has a `FlowRepresentable.WorkflowInput` of `String` but the previous item passes an `Int` forward, that workflow is malformed. It's possible for a `FlowRepresentable` to declare a `FlowRepresentable.WorkflowInput` of `Never` if it does not take in data, `Any` if it can intake multiple types, or `AnyWorkflow.PassedArgs` if it can handle being passed no data, or data of any kind. \ No newline at end of file From e11f3da17131f5b43072f433b032f1003a110b6d Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 11:54:37 -0600 Subject: [PATCH 12/22] [new-docs] - Added an abstract for how to use SwiftCurrent with UIKit - TT --- .github/abstract/How to use SwiftCurrent with UIKit.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/abstract/How to use SwiftCurrent with UIKit.md diff --git a/.github/abstract/How to use SwiftCurrent with UIKit.md b/.github/abstract/How to use SwiftCurrent with UIKit.md new file mode 100644 index 000000000..48bbf160c --- /dev/null +++ b/.github/abstract/How to use SwiftCurrent with UIKit.md @@ -0,0 +1 @@ +SwiftCurrent works well with UIKit. To work correctly it does require `FlowRepresentable`s to be `UIViewController`s and not `UIView`s. It comes with [support for Storyboards](using-storyboards.html) with `StoryboardLoadable` and [programmatic views](using-programmatic-views.html). \ No newline at end of file From ebae754ed4f43103c7ec0fb6d2898e4e14cbb64f Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 12:07:35 -0600 Subject: [PATCH 13/22] [new-docs] - Added and udpated abstracts, mostly around Creating Workflows in UIKit - TT --- .../abstract/Creating Workflows in SwiftUI.md | 2 +- .../abstract/Creating Workflows in UIKit.md | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 .github/abstract/Creating Workflows in UIKit.md diff --git a/.github/abstract/Creating Workflows in SwiftUI.md b/.github/abstract/Creating Workflows in SwiftUI.md index e58b1f27d..54bbfee87 100644 --- a/.github/abstract/Creating Workflows in SwiftUI.md +++ b/.github/abstract/Creating Workflows in SwiftUI.md @@ -19,7 +19,7 @@ struct FirstView: View, FlowRepresentable { > Note: The `_workflowPointer` is needed as an anchor point for your `Workflow`. You do not have to worry about setting it, you merely need space for it on your structs. SwiftUI actually does the exact same thing with a `_location` variable, it's just that Apple has secret compiler magic to hide that. Unfortunately, that compiler magic is not shared. -> Note: `Workflow.proceedInWorkflow()` is what you call to have your view move forward to the next item in the `Workflow` it is part of. +> Note: `FlowRepresentable.proceedInWorkflow()` is what you call to have your view move forward to the next item in the `Workflow` it is part of. ### Step 2: Define your `WorkflowLauncher`. This indicates whether the workflow is shown and describes what items are in it. diff --git a/.github/abstract/Creating Workflows in UIKit.md b/.github/abstract/Creating Workflows in UIKit.md new file mode 100644 index 000000000..dee541580 --- /dev/null +++ b/.github/abstract/Creating Workflows in UIKit.md @@ -0,0 +1,43 @@ +### Step 1: +To create workflows in UIKit you should start with a `UIViewController` that should be part of a `Workflow` and modify it to be `FlowRepresentable` + +#### Example: +```swift +import UIKit +import SwiftCurrent +import SwiftCurrent_UIKit + +// This screen shows an employee only screen +class FirstViewController: UIWorkflowItem, FlowRepresentable { // SwiftCurrent + private let email: String + private let finishButton = UIButton() + + required init(with email: String) { // SwiftCurrent + self.email = email + super.init(nibName: nil, bundle: nil) + // Configure your view programmatically or look at StoryboardLoadable to use storyboards. + } + + required init?(coder: NSCoder) { nil } + + @objc private func finishPressed() { + proceedInWorkflow(email) // SwiftCurrent + } +} +``` + +> Note: `FlowRepresentable.proceedInWorkflow()` is what you call to have your view move forward to the next item in the `Workflow` it is part of. + +### Step 2: +Define your `Workflow` and launch it. This is what allows you to configure or re-order your workflow. + +#### Example: +```swift +// From the ViewController you'd like to launch the workflow +@objc private func didTapLaunchWorkflow() { + let workflow = Workflow(FirstViewController.self) // SwiftCurrent + .thenPresent(SecondViewController.self) // SwiftCurrent + + launchInto(workflow, args: "Some starting arguments") +} +``` \ No newline at end of file From d6612d6813fa73d6e2eaa0e63a7cde39b429dfce Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 12:18:45 -0600 Subject: [PATCH 14/22] [new-docs] - Added an abstract for controlling presentation - TT --- .github/abstract/Controlling Presentation.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/abstract/Controlling Presentation.md diff --git a/.github/abstract/Controlling Presentation.md b/.github/abstract/Controlling Presentation.md new file mode 100644 index 000000000..c325a7157 --- /dev/null +++ b/.github/abstract/Controlling Presentation.md @@ -0,0 +1,12 @@ +SwiftCurrent allows you to control how your workflow presents its `FlowRepresentable`s. This control over presentation is different for UIKit and SwiftUI. You can also control `FlowPersistence` which is a description for what should happen to an item in a `workflow` if it's been skipped, or once the workflow has proceeded. + +### UIKit +In UIKit you control presentation using `LaunchStyle.PresentationType`. The default is a contextual presentation mode. If it detects you are in a navigation view, it'll present by pushing onto the navigation stack. If it cannot detect a navigation view it presents modally. Alternatively you can explicitly state you'd like it to present modally or in a navigation stack when you define your `workflow`. + +### In SwiftUI +In SwiftUI you control presentation using `LaunchStyle.SwiftUI.PresentationType`. The default is simple view replacement. This is especially powerful because your workflows in SwiftUI do not need to be an entire screen, they can be just part of a view. Using the default presentation type you can also get fine grained control over animations. You can also explicitly state you'd like it to present modally (using a sheet, or fullScreenCover) or in a navigation stack when you define your `WorkflowLauncher`. + +### Persistence +You can control what happens to items in your workflow using `FlowPersistence`. Using `FlowPersistence.persistWhenSkipped` means that when `FlowRepresentable.shouldLoad` returns false the item is still stored on the workflow. If for example, you're in a navigation stack this means the item *is* skipped, but you can back up to it. + +using `FlowPersistence.removedAfterProceeding` means once the `workflow` has proceeded, the item is removed, references to it are cleaned up, and it is removed from any back stacks. \ No newline at end of file From 933d38a31cef06022a002d114135fffad62ce96e Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 12:27:53 -0600 Subject: [PATCH 15/22] [new-docs] - Added an abstract for type erasure - TT --- .github/abstract/Type Erasure.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .github/abstract/Type Erasure.md diff --git a/.github/abstract/Type Erasure.md b/.github/abstract/Type Erasure.md new file mode 100644 index 000000000..11930cd56 --- /dev/null +++ b/.github/abstract/Type Erasure.md @@ -0,0 +1,4 @@ +Sometimes it may be desireable to explicitly remove type information. Often times this is when you want to pass around types with complicated generic signatures. SwiftCurrent, much like many of Apple's standard libraries, ships with several type erasers for your convenience. + +### `AnyWorkflow.PassedArgs` +The type `AnyWorkflow.PassedArgs` is worth calling out separately. It's very similar to Swift's standard `Optional` type, but with a crucial difference. Consumers of SwiftCurrent need to be able to clearly differentiate between `nil` being passed in a `workflow` that proceeded and no arguments at all being passed. So if a `FlowRepresentable.WorkflowInput` is `Any?` that means it can accept any kind of data, even if that data is optional, but data *must* be passed to it. If a `FlowRepresentable.WorkflowInput` is `AnyWorkflow.PassedArgs` it means that it can take any kind of data, including nil data, OR it can take no data at all. \ No newline at end of file From bc206c4aacb9d0fb5b0bf78710714ac2eb246d18 Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 12:30:40 -0600 Subject: [PATCH 16/22] [new-docs] - Added an abstract for underlying types - TT --- .github/abstract/Underlying Types.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/abstract/Underlying Types.md diff --git a/.github/abstract/Underlying Types.md b/.github/abstract/Underlying Types.md new file mode 100644 index 000000000..e0b42b094 --- /dev/null +++ b/.github/abstract/Underlying Types.md @@ -0,0 +1 @@ +These types are required to make SwiftCurrent function. Most of these are public symbols because of the modular design of SwiftCurrent. Some of them are public in case you want to extend SwiftCurrent to do even more. Generally speaking, these types are not something you need to worry about. \ No newline at end of file From 63171780cc082f9de8a069fb14b2d0a6a46f38a9 Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 13:57:08 -0600 Subject: [PATCH 17/22] [new-docs] - Fixed the abstracts that referred to lowercase workflow - TT --- .github/abstract/Controlling Presentation.md | 6 +++--- .github/abstract/Creating Workflows.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/abstract/Controlling Presentation.md b/.github/abstract/Controlling Presentation.md index c325a7157..4b412b494 100644 --- a/.github/abstract/Controlling Presentation.md +++ b/.github/abstract/Controlling Presentation.md @@ -1,7 +1,7 @@ -SwiftCurrent allows you to control how your workflow presents its `FlowRepresentable`s. This control over presentation is different for UIKit and SwiftUI. You can also control `FlowPersistence` which is a description for what should happen to an item in a `workflow` if it's been skipped, or once the workflow has proceeded. +SwiftCurrent allows you to control how your workflow presents its `FlowRepresentable`s. This control over presentation is different for UIKit and SwiftUI. You can also control `FlowPersistence` which is a description for what should happen to an item in a `Workflow` if it's been skipped, or once the workflow has proceeded. ### UIKit -In UIKit you control presentation using `LaunchStyle.PresentationType`. The default is a contextual presentation mode. If it detects you are in a navigation view, it'll present by pushing onto the navigation stack. If it cannot detect a navigation view it presents modally. Alternatively you can explicitly state you'd like it to present modally or in a navigation stack when you define your `workflow`. +In UIKit you control presentation using `LaunchStyle.PresentationType`. The default is a contextual presentation mode. If it detects you are in a navigation view, it'll present by pushing onto the navigation stack. If it cannot detect a navigation view it presents modally. Alternatively you can explicitly state you'd like it to present modally or in a navigation stack when you define your `Workflow`. ### In SwiftUI In SwiftUI you control presentation using `LaunchStyle.SwiftUI.PresentationType`. The default is simple view replacement. This is especially powerful because your workflows in SwiftUI do not need to be an entire screen, they can be just part of a view. Using the default presentation type you can also get fine grained control over animations. You can also explicitly state you'd like it to present modally (using a sheet, or fullScreenCover) or in a navigation stack when you define your `WorkflowLauncher`. @@ -9,4 +9,4 @@ In SwiftUI you control presentation using `LaunchStyle.SwiftUI.PresentationType` ### Persistence You can control what happens to items in your workflow using `FlowPersistence`. Using `FlowPersistence.persistWhenSkipped` means that when `FlowRepresentable.shouldLoad` returns false the item is still stored on the workflow. If for example, you're in a navigation stack this means the item *is* skipped, but you can back up to it. -using `FlowPersistence.removedAfterProceeding` means once the `workflow` has proceeded, the item is removed, references to it are cleaned up, and it is removed from any back stacks. \ No newline at end of file +Using `FlowPersistence.removedAfterProceeding` means once the `Workflow` has proceeded, the item is removed, references to it are cleaned up, and it is removed from any back stacks. \ No newline at end of file diff --git a/.github/abstract/Creating Workflows.md b/.github/abstract/Creating Workflows.md index 967ef413c..1bffd6c26 100644 --- a/.github/abstract/Creating Workflows.md +++ b/.github/abstract/Creating Workflows.md @@ -1,8 +1,8 @@ ### What is a workflow? -A `workflow` is a description for a sequence of `FlowRepresentable`. Those operations are normally displaying screens or views. There are different ways of [creating workflows in SwiftUI](Creating%20Workflows%20in%20SwiftUI.html) and [creating workflows in UIKit](Creating%20Workflows%20in%20UIKit.html). +A `Workflow` is a description for a sequence of `FlowRepresentable`. Those operations are normally displaying screens or views. There are different ways of [creating workflows in SwiftUI](Creating%20Workflows%20in%20SwiftUI.html) and [creating workflows in UIKit](Creating%20Workflows%20in%20UIKit.html). ### What is a `FlowRepresentable`? -A `FlowRepresentable` is a protocol that describes a type that can appear in a `workflow`. It optionally declares `FlowRepresentable.WorkflowInput` and `FlowRepresentable.WorkflowOutput` indicating whether it requires data or whether it passes data forward. It also provides an initializer so that it can be created by the `workflow`. Once an item conforms to `FlowRepresentable` it is capable of being injected into any `workflow`. +A `FlowRepresentable` is a protocol that describes a type that can appear in a `Workflow`. It optionally declares `FlowRepresentable.WorkflowInput` and `FlowRepresentable.WorkflowOutput` indicating whether it requires data or whether it passes data forward. It also provides an initializer so that it can be created by the `Workflow`. Once an item conforms to `FlowRepresentable` it is capable of being injected into any `Workflow`. ### Valid workflow sequences Workflows enforce (either at compile-time or run-time) that the sequence of `FlowRepresentables` are well-formed. For example if a particular `FlowRepresentable` has a `FlowRepresentable.WorkflowInput` of `String` but the previous item passes an `Int` forward, that workflow is malformed. It's possible for a `FlowRepresentable` to declare a `FlowRepresentable.WorkflowInput` of `Never` if it does not take in data, `Any` if it can intake multiple types, or `AnyWorkflow.PassedArgs` if it can handle being passed no data, or data of any kind. \ No newline at end of file From f04b04f5d885c2f7b3c781870adc394af412b531 Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 14:47:11 -0600 Subject: [PATCH 18/22] [new-docs] - Fixed docs post processing so that it does not mangle links once it's nested in the folder structure - TT RAG Co-authored-by: Richard Gist --- .../Sources/DocsPostProcessor/DocsPostProcessor.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift index 7fee7b192..ed2015871 100644 --- a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift +++ b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift @@ -46,7 +46,8 @@ struct DocsPostProcessor: ParsableCommand { if let nav = try? document.select("nav").first() { if let firstNavLink = try nav.getElementsByClass("nav-group-name-link").first(), URL(fileURLWithPath: try firstNavLink.attr("href")).lastPathComponent == "Overview.html" { - try firstNavLink.attr("href", "index.html") + let oldURL = URL(fileURLWithPath: try firstNavLink.attr("href")) + try firstNavLink.attr("href", oldURL.deletingLastPathComponent().appendingPathComponent("index.html")) } else { throw Err.noOverviewFound } From 574fa516ec3e44751439319c132dbc4e46b3a100 Mon Sep 17 00:00:00 2001 From: Tyler Thompson <33705774+Tyler-Keith-Thompson@users.noreply.github.com> Date: Fri, 10 Sep 2021 14:49:33 -0600 Subject: [PATCH 19/22] Update .github/DocsPostProcessor/Package.swift Co-authored-by: Richard Gist --- .github/DocsPostProcessor/Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/DocsPostProcessor/Package.swift b/.github/DocsPostProcessor/Package.swift index 1f1f7b94b..8075a5fb9 100644 --- a/.github/DocsPostProcessor/Package.swift +++ b/.github/DocsPostProcessor/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.5 +// swift-tools-version:5.4 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription From fad9c4f0ec1a4fbca051dddfb16a5c79238f9347 Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 15:09:07 -0600 Subject: [PATCH 20/22] [new-docs] - the problem was fileURLWithPath, despite the fact that this is a file URL. That ended up causing all kinds of bizarre behavior that was undesirable, now we are good - TT --- .../Sources/DocsPostProcessor/DocsPostProcessor.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift index ed2015871..a77d962b7 100644 --- a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift +++ b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift @@ -20,7 +20,7 @@ struct DocsPostProcessor: ParsableCommand { let url = URL(fileURLWithPath: FileManager.default.currentDirectoryPath).appendingPathComponent(path) var files: [URL] = (url.pathExtension == "html") ? [url] : [] if url.pathExtension != "html", let enumerator = FileManager.default.enumerator(at: url, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles]) { - for case let fileURL as URL in enumerator { + for case let fileURL as URL in enumerator /*where fileURL.pathComponents.contains("SwiftCurrent.docset")*/ { let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey]) if fileAttributes.isRegularFile == true, fileURL.pathExtension == "html" { files.append(fileURL) @@ -45,9 +45,9 @@ struct DocsPostProcessor: ParsableCommand { func replaceOverviewWithReadme(document: Document) throws { if let nav = try? document.select("nav").first() { if let firstNavLink = try nav.getElementsByClass("nav-group-name-link").first(), - URL(fileURLWithPath: try firstNavLink.attr("href")).lastPathComponent == "Overview.html" { - let oldURL = URL(fileURLWithPath: try firstNavLink.attr("href")) - try firstNavLink.attr("href", oldURL.deletingLastPathComponent().appendingPathComponent("index.html")) + let oldUrl = URL(string: try firstNavLink.attr("href")), + oldUrl.lastPathComponent == "Overview.html" { + try firstNavLink.attr("href", oldUrl.deletingLastPathComponent().appendingPathComponent("index.html").absoluteString) } else { throw Err.noOverviewFound } From bc26e26388a3a8f245f04df1aed192996ecc50b0 Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 15:34:13 -0600 Subject: [PATCH 21/22] [new-docs] - Cleaned up comment - TT --- .../Sources/DocsPostProcessor/DocsPostProcessor.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift index a77d962b7..87ed69d9f 100644 --- a/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift +++ b/.github/DocsPostProcessor/Sources/DocsPostProcessor/DocsPostProcessor.swift @@ -20,7 +20,7 @@ struct DocsPostProcessor: ParsableCommand { let url = URL(fileURLWithPath: FileManager.default.currentDirectoryPath).appendingPathComponent(path) var files: [URL] = (url.pathExtension == "html") ? [url] : [] if url.pathExtension != "html", let enumerator = FileManager.default.enumerator(at: url, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles]) { - for case let fileURL as URL in enumerator /*where fileURL.pathComponents.contains("SwiftCurrent.docset")*/ { + for case let fileURL as URL in enumerator { let fileAttributes = try fileURL.resourceValues(forKeys:[.isRegularFileKey]) if fileAttributes.isRegularFile == true, fileURL.pathExtension == "html" { files.append(fileURL) From d6321ed40147a5ea9b8151b0c765eac0e53ad1fc Mon Sep 17 00:00:00 2001 From: Tyler Thompson Date: Fri, 10 Sep 2021 15:52:06 -0600 Subject: [PATCH 22/22] [new-docs] - Added a line about tuples, just for Richard - TT RAG Co-authored-by: Richard Gist --- .github/abstract/Creating Workflows.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/abstract/Creating Workflows.md b/.github/abstract/Creating Workflows.md index 1bffd6c26..8398af43a 100644 --- a/.github/abstract/Creating Workflows.md +++ b/.github/abstract/Creating Workflows.md @@ -5,4 +5,4 @@ A `Workflow` is a description for a sequence of `FlowRepresentable`. Those opera A `FlowRepresentable` is a protocol that describes a type that can appear in a `Workflow`. It optionally declares `FlowRepresentable.WorkflowInput` and `FlowRepresentable.WorkflowOutput` indicating whether it requires data or whether it passes data forward. It also provides an initializer so that it can be created by the `Workflow`. Once an item conforms to `FlowRepresentable` it is capable of being injected into any `Workflow`. ### Valid workflow sequences -Workflows enforce (either at compile-time or run-time) that the sequence of `FlowRepresentables` are well-formed. For example if a particular `FlowRepresentable` has a `FlowRepresentable.WorkflowInput` of `String` but the previous item passes an `Int` forward, that workflow is malformed. It's possible for a `FlowRepresentable` to declare a `FlowRepresentable.WorkflowInput` of `Never` if it does not take in data, `Any` if it can intake multiple types, or `AnyWorkflow.PassedArgs` if it can handle being passed no data, or data of any kind. \ No newline at end of file +Workflows enforce (either at compile-time or run-time) that the sequence of `FlowRepresentables` are well-formed. For example if a particular `FlowRepresentable` has a `FlowRepresentable.WorkflowInput` of `String` but the previous item passes an `Int` forward, that workflow is malformed. It's possible for a `FlowRepresentable` to declare a `FlowRepresentable.WorkflowInput` of `Never` if it does not take in data, `Any` if it can intake multiple types, or `AnyWorkflow.PassedArgs` if it can handle being passed no data, or data of any kind. Lastly, if your `FlowRepresentable.WorkflowInput` needs to take in multiple values you can use a tuple. \ No newline at end of file