Skip to content

Commit a9a1a01

Browse files
authored
Enable metadata keys and values to be modified (#39)
This change introduces two new `Modifier.Target` instances: `metadataKeys` and `metadataValues`, which can be used to customize how Ink parses metadata. This in turn enables Publish plugins to be written that bridges the gap between Publish’s built-in metadata format and that of external tools, such as other static site generators or CMSs.
1 parent c88bbce commit a9a1a01

4 files changed

Lines changed: 49 additions & 2 deletions

File tree

Sources/Ink/API/MarkdownParser.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public struct MarkdownParser {
5353
do {
5454
if metadata == nil, fragments.isEmpty, reader.currentCharacter == "-" {
5555
if let parsedMetadata = try? Metadata.readOrRewind(using: &reader) {
56-
metadata = parsedMetadata
56+
metadata = parsedMetadata.applyingModifiers(modifiers)
5757
continue
5858
}
5959
}

Sources/Ink/API/Modifier.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
public struct Modifier {
1717
/// The type of input that each modifier is given, which both
1818
/// contains the HTML that was generated for a fragment, and
19-
/// its raw Markdown representation.
19+
/// its raw Markdown representation. Note that for metadata
20+
/// targets, the two input arguments will be equivalent.
2021
public typealias Input = (html: String, markdown: Substring)
2122
/// The type of closure that Modifiers are based on. Each
2223
/// modifier is given a set of input, and is expected to return
@@ -39,6 +40,8 @@ public struct Modifier {
3940

4041
public extension Modifier {
4142
enum Target {
43+
case metadataKeys
44+
case metadataValues
4245
case blockquotes
4346
case codeBlocks
4447
case headings

Sources/Ink/Internal/Metadata.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,26 @@ internal struct Metadata: Readable {
4242

4343
throw Reader.Error()
4444
}
45+
46+
func applyingModifiers(_ modifiers: ModifierCollection) -> Self {
47+
var modified = self
48+
49+
modifiers.applyModifiers(for: .metadataKeys) { modifier in
50+
for (key, value) in modified.values {
51+
let newKey = modifier.closure((key, Substring(key)))
52+
modified.values[key] = nil
53+
modified.values[newKey] = value
54+
}
55+
}
56+
57+
modifiers.applyModifiers(for: .metadataValues) { modifier in
58+
modified.values = modified.values.mapValues { value in
59+
modifier.closure((value, Substring(value)))
60+
}
61+
}
62+
63+
return modified
64+
}
4565
}
4666

4767
private extension Metadata {

Tests/InkTests/MarkdownTests.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,29 @@ final class MarkdownTests: XCTestCase {
6767
XCTAssertEqual(markdown.html, "<h1>Title</h1>")
6868
}
6969

70+
func testMetadataModifiers() {
71+
let parser = MarkdownParser(modifiers: [
72+
Modifier(target: .metadataKeys) { key, _ in
73+
"ModifiedKey-" + key
74+
},
75+
Modifier(target: .metadataValues) { value, _ in
76+
"ModifiedValue-" + value
77+
}
78+
])
79+
80+
let markdown = parser.parse("""
81+
---
82+
keyA: valueA
83+
keyB: valueB
84+
---
85+
""")
86+
87+
XCTAssertEqual(markdown.metadata, [
88+
"ModifiedKey-keyA" : "ModifiedValue-valueA",
89+
"ModifiedKey-keyB" : "ModifiedValue-valueB"
90+
])
91+
}
92+
7093
func testPlainTextTitle() {
7194
let markdown = MarkdownParser().parse("""
7295
# Hello, world!
@@ -115,6 +138,7 @@ extension MarkdownTests {
115138
("testDiscardingEmptyMetadataValues", testDiscardingEmptyMetadataValues),
116139
("testMergingOrphanMetadataValueIntoPreviousOne", testMergingOrphanMetadataValueIntoPreviousOne),
117140
("testMissingMetadata", testMissingMetadata),
141+
("testMetadataModifiers", testMetadataModifiers),
118142
("testPlainTextTitle", testPlainTextTitle),
119143
("testRemovingTrailingMarkersFromTitle", testRemovingTrailingMarkersFromTitle),
120144
("testConvertingFormattedTitleTextToPlainText", testConvertingFormattedTitleTextToPlainText),

0 commit comments

Comments
 (0)