Skip to content

Commit

Permalink
feat: Bundle an publicationDateInFilename item processor with Saga
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinrenskers committed Feb 7, 2025
1 parent a045e1e commit fb5492e
Show file tree
Hide file tree
Showing 10 changed files with 1,128 additions and 35 deletions.
28 changes: 1 addition & 27 deletions Example/Sources/Example/run.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,8 @@ extension Item where M == ArticleMetadata {
}
}

// An example of a simple page processor that takes files such as "2021-01-27-post-with-date-in-filename"
// and uses the date within the filename as the publication date.
func itemProcessor(item: Item<ArticleMetadata>) async {
// If the filename starts with a valid date, use that as the Page's date and strip it from the destination path
let first10 = String(item.relativeSource.lastComponentWithoutExtension.prefix(10))
guard first10.count == 10, let date = Run.pageProcessorDateFormatter.date(from: first10) else {
return
}

// Set the date
item.published = date

// And remove the first 11 characters from the filename
let first11 = String(item.relativeSource.lastComponentWithoutExtension.prefix(11))
item.relativeDestination = Path(
item.relativeSource.string.replacingOccurrences(of: first11, with: "")
).makeOutputPath(itemWriteMode: .moveToSubfolder)
}

@main
struct Run {
static var pageProcessorDateFormatter: DateFormatter = {
let pageProcessorDateFormatter = DateFormatter()
pageProcessorDateFormatter.dateFormat = "yyyy-MM-dd"
pageProcessorDateFormatter.timeZone = .current
return pageProcessorDateFormatter
}()

static func main() async throws {
try await Saga(input: "content", output: "deploy")
// All markdown files within the "articles" subfolder will be parsed to html,
Expand All @@ -65,7 +39,7 @@ struct Run {
folder: "articles",
metadata: ArticleMetadata.self,
readers: [.parsleyMarkdownReader],
itemProcessor: itemProcessor,
itemProcessor: publicationDateInFilename,
filter: \.public,
writers: [
.itemWriter(swim(renderArticle)),
Expand Down
6 changes: 2 additions & 4 deletions Sources/Saga/Saga.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ import PathKit
/// // All files in the input folder will be parsed to html, and written to the output folder.
/// .register(
/// metadata: EmptyMetadata.self,
/// readers: [.parsleyMarkdownReader()],
/// writers: [
/// .itemWriter(swim(renderPage))
/// ]
/// readers: [.parsleyMarkdownReader],
/// writers: [.itemWriter(swim(renderPage))]
/// )
///
/// // Run the step we registered above
Expand Down
46 changes: 46 additions & 0 deletions Sources/Saga/utils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import PathKit
import Foundation

/// Run multiple item processors in sequence.
///
/// ```swift
/// .register(
/// metadata: EmptyMetadata.self,
/// readers: [.parsleyMarkdownReader],
/// itemProcessor: sequence(publicationDateInFilename, addExclamationPointToTitle)
/// writers: [.itemWriter(swim(renderPage))]
/// )
/// ```
public func sequence<M>(_ processors: ((Item<M>) async -> Void)...) -> (Item<M>) async -> Void {
return { item in
for processor in processors {
await processor(item)
}
}
}

private let publicationDateFormatter: DateFormatter = {
let pageProcessorDateFormatter = DateFormatter()
pageProcessorDateFormatter.dateFormat = "yyyy-MM-dd"
pageProcessorDateFormatter.timeZone = .current
return pageProcessorDateFormatter
}()

/// An item processor that takes files such as "2021-01-27-post-with-date-in-filename"
/// and uses the date within the filename as the publication date.
public func publicationDateInFilename<M>(item: Item<M>) async {
// If the filename starts with a valid date, use that as the Page's date and strip it from the destination path
let first10 = String(item.relativeSource.lastComponentWithoutExtension.prefix(10))
guard first10.count == 10, let date = publicationDateFormatter.date(from: first10) else {
return
}

// Set the date
item.published = date

// And remove the first 11 characters from the filename
let first11 = String(item.relativeSource.lastComponentWithoutExtension.prefix(11))
item.relativeDestination = Path(
item.relativeSource.string.replacingOccurrences(of: first11, with: "")
).makeOutputPath(itemWriteMode: .moveToSubfolder)
}
190 changes: 190 additions & 0 deletions docs/data/documentation/saga.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,15 @@
],
"title" : "Structures"
},
{
"anchor" : "Functions",
"generated" : true,
"identifiers" : [
"doc:\/\/Saga\/documentation\/Saga\/publicationDateInFilename(item:)",
"doc:\/\/Saga\/documentation\/Saga\/sequence(_:)"
],
"title" : "Functions"
},
{
"anchor" : "Type-Aliases",
"generated" : true,
Expand Down Expand Up @@ -877,6 +886,187 @@
"type" : "topic",
"url" : "\/documentation\/saga\/writer"
},
"doc://Saga/documentation/Saga/publicationDateInFilename(item:)": {
"abstract" : [
{
"text" : "An item processor that takes files such as “2021-01-27-post-with-date-in-filename”",
"type" : "text"
},
{
"text" : " ",
"type" : "text"
},
{
"text" : "and uses the date within the filename as the publication date.",
"type" : "text"
}
],
"fragments" : [
{
"kind" : "keyword",
"text" : "func"
},
{
"kind" : "text",
"text" : " "
},
{
"kind" : "identifier",
"text" : "publicationDateInFilename"
},
{
"kind" : "text",
"text" : "<"
},
{
"kind" : "genericParameter",
"text" : "M"
},
{
"kind" : "text",
"text" : ">("
},
{
"kind" : "externalParam",
"text" : "item"
},
{
"kind" : "text",
"text" : ": "
},
{
"kind" : "typeIdentifier",
"preciseIdentifier" : "s:4Saga4ItemC",
"text" : "Item"
},
{
"kind" : "text",
"text" : "<"
},
{
"kind" : "typeIdentifier",
"text" : "M"
},
{
"kind" : "text",
"text" : ">) "
},
{
"kind" : "keyword",
"text" : "async"
}
],
"identifier" : "doc:\/\/Saga\/documentation\/Saga\/publicationDateInFilename(item:)",
"kind" : "symbol",
"role" : "symbol",
"title" : "publicationDateInFilename(item:)",
"type" : "topic",
"url" : "\/documentation\/saga\/publicationdateinfilename(item:)"
},
"doc://Saga/documentation/Saga/sequence(_:)": {
"abstract" : [
{
"text" : "Run multiple item processors in sequence.",
"type" : "text"
}
],
"fragments" : [
{
"kind" : "keyword",
"text" : "func"
},
{
"kind" : "text",
"text" : " "
},
{
"kind" : "identifier",
"text" : "sequence"
},
{
"kind" : "text",
"text" : "<"
},
{
"kind" : "genericParameter",
"text" : "M"
},
{
"kind" : "text",
"text" : ">((("
},
{
"kind" : "typeIdentifier",
"preciseIdentifier" : "s:4Saga4ItemC",
"text" : "Item"
},
{
"kind" : "text",
"text" : "<"
},
{
"kind" : "typeIdentifier",
"text" : "M"
},
{
"kind" : "text",
"text" : ">) "
},
{
"kind" : "keyword",
"text" : "async"
},
{
"kind" : "text",
"text" : " -> "
},
{
"kind" : "typeIdentifier",
"preciseIdentifier" : "s:s4Voida",
"text" : "Void"
},
{
"kind" : "text",
"text" : ")...) -> ("
},
{
"kind" : "typeIdentifier",
"preciseIdentifier" : "s:4Saga4ItemC",
"text" : "Item"
},
{
"kind" : "text",
"text" : "<"
},
{
"kind" : "typeIdentifier",
"text" : "M"
},
{
"kind" : "text",
"text" : ">) "
},
{
"kind" : "keyword",
"text" : "async"
},
{
"kind" : "text",
"text" : " -> "
},
{
"kind" : "typeIdentifier",
"preciseIdentifier" : "s:s4Voida",
"text" : "Void"
}
],
"identifier" : "doc:\/\/Saga\/documentation\/Saga\/sequence(_:)",
"kind" : "symbol",
"role" : "symbol",
"title" : "sequence(_:)",
"type" : "topic",
"url" : "\/documentation\/saga\/sequence(_:)"
},
"https://github.com/JohnSundell/Publish": {
"identifier" : "https:\/\/github.com\/JohnSundell\/Publish",
"title" : "Publish",
Expand Down
Loading

0 comments on commit fb5492e

Please sign in to comment.