diff --git a/Sources/HTMLKit/Framework/Rendering/Markdown/MarkdownString.swift b/Sources/HTMLKit/Framework/Rendering/Markdown/MarkdownString.swift index 2c2bf5fe..c5370ef6 100644 --- a/Sources/HTMLKit/Framework/Rendering/Markdown/MarkdownString.swift +++ b/Sources/HTMLKit/Framework/Rendering/Markdown/MarkdownString.swift @@ -15,3 +15,70 @@ public struct MarkdownString: Content { self.raw = string() } } + +/// Extends string interpolation to include helper functions for Markdown +extension String.StringInterpolation { + + /// Enables interpolation of italic text in Markdown format + /// + /// ``` + /// \(italic: "text") + /// ``` + public mutating func appendInterpolation(italic text: String) { + appendLiteral("_\(text)_") + } + + /// Enables interpolation of bold text in Markdown format + /// + /// ``` + /// \(bold: "text") + /// ``` + mutating public func appendInterpolation(bold text: String) { + appendLiteral("**\(text)**") + } + + /// Enables interpolation of strikethrough text in Markdown format + /// + /// ``` + /// \(strike: "text") + /// ``` + public mutating func appendInterpolation(strike text: String) { + appendLiteral("~\(text)~") + } + + /// Enables interpolation of a hyperlink in Markdown format + /// + /// ``` + /// \(link: "https://www.example.com") + /// ``` + public mutating func appendInterpolation(link url: String) { + appendLiteral("[\(url)](\(url)") + } + + /// Enables interpolation of a email link in Markdown format + /// + /// ``` + /// \(email: "example@example.com") + /// ``` + public mutating func appendInterpolation(email address: String) { + appendLiteral("[\(address)](mailto:\(address)") + } + + /// Enables interpolation of a phone number link in Markdown format + /// + /// ``` + /// \(phone: "123-456-7890") + /// ``` + public mutating func appendInterpolation(phone number: String) { + appendLiteral("[\(number)](tel:\(number)") + } + + /// Enables interpolation of italicized text in Markdown format + /// + /// ``` + /// \(code: "code") + /// ``` + public mutating func appendInterpolation(code text: String) { + appendLiteral("`\(text)`") + } +} diff --git a/Tests/HTMLKitTests/RenderingTests.swift b/Tests/HTMLKitTests/RenderingTests.swift index cf77ede7..87508a65 100644 --- a/Tests/HTMLKitTests/RenderingTests.swift +++ b/Tests/HTMLKitTests/RenderingTests.swift @@ -232,112 +232,123 @@ final class RenderingTests: XCTestCase { ) } + /// Tests the Markdown rendering for italic emphasis + /// + /// The renderer is expected to convert the Markdown syntax into the HTML equivalent func testRenderingItalicMarkdown() throws { let view = TestView { - Paragraph { - MarkdownString("*italic*") - } - Paragraph { - MarkdownString("_italic_") - } + MarkdownString("*italic*") + MarkdownString("_italic_") + MarkdownString("\(italic: "italic")") } XCTAssertEqual(try renderer.render(view: view), """ -

italic

\ -

italic

+ italic\ + italic\ + italic """ ) } + /// Tests the Markdown rendering for bold emphasis + /// + /// The renderer is expected to convert the Markdown syntax into the HTML equivalent func testRenderingBoldMarkdown() throws { let view = TestView { - Paragraph { - MarkdownString("**bold**") - } - Paragraph { - MarkdownString("__bold__") - } + MarkdownString("**bold**") + MarkdownString("__bold__") + MarkdownString("\(bold: "bold")") } XCTAssertEqual(try renderer.render(view: view), """ -

bold

\ -

bold

+ bold\ + bold\ + bold """ ) } + /// Tests the Markdown rendering for bold and italic emphasis + /// + /// The renderer is expected to convert the Markdown syntax into the HTML equivalent func testRenderingBoldItalicMarkdown() throws { let view = TestView { - Paragraph { - MarkdownString("***bold and italic***") - } - Paragraph { - MarkdownString("___bold and italic___") - } + MarkdownString("***bold and italic***") + MarkdownString("___bold and italic___") } XCTAssertEqual(try renderer.render(view: view), """ -

bold and italic

\ -

bold and italic

+ bold and italic\ + bold and italic """ ) } + /// Tests the Markdown rendering for inline code emphasis + /// + /// The renderer is expected to convert the Markdown syntax into the HTML equivalent func testRenderingMonospaceMarkdown() throws { let view = TestView { - Paragraph { - MarkdownString("`code`") - } + MarkdownString("`code`") + MarkdownString("\(code: "code")") } XCTAssertEqual(try renderer.render(view: view), """ -

code

+ code\ + code """ ) } + /// Tests the Markdown rendering for strikethrough emphasis + /// + /// The renderer is expected to convert the Markdown syntax into the HTML equivalent func testRenderingStrikeThroughMarkdown() throws { let view = TestView { - Paragraph { - MarkdownString("~strikethrough~") - } - Paragraph { - MarkdownString("~~strikethrough~~") - } + MarkdownString("~strikethrough~") + MarkdownString("~~strikethrough~~") + MarkdownString("\(strike: "strikethrough")") } XCTAssertEqual(try renderer.render(view: view), """ -

strikethrough

\ -

strikethrough

+ strikethrough\ + strikethrough\ + strikethrough """ ) } + /// Tests the Markdown rendering for links + /// + /// The renderer is expected to convert the Markdown syntax into the HTML equivalent func testRenderingLinkMarkdown() throws { let view = TestView { - Paragraph { - MarkdownString("[Link](https://www.vapor.codes)") - } + MarkdownString("[Link](https://www.vapor.codes)") + MarkdownString("\(link: "https://www.vapor.codes")") + MarkdownString("\(email: "alone@home.com")") } XCTAssertEqual(try renderer.render(view: view), """ -

Link

+ Link\ + https://www.vapor.codes\ + alone@home.com """ ) } + /// Tests the Markdown rendering of a paragraph with multiple emphasis elements func testRenderingMarkdownParagraph() throws { let view = TestView { @@ -353,21 +364,23 @@ final class RenderingTests: XCTestCase { ) } + /// Tests the Markdown rendering of nested emphasis elements + /// + /// The renderer is expected to convert the Markdown syntax into the HTML equivalent, + /// while preserving the nesting. func testRenderingNestedMarkdown() throws { let view = TestView { - Paragraph { - MarkdownString { - """ - **This text is _extremely_ important.** - """ - } + MarkdownString { + """ + **This text is _extremely_ important.** + """ } } XCTAssertEqual(try renderer.render(view: view), """ -

This text is extremely important.

+ This text is extremely important. """ ) }