Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add helper functions for markdown rendering #155

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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: "[email protected]")
/// ```
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)`")
}
}
107 changes: 60 additions & 47 deletions Tests/HTMLKitTests/RenderingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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),
"""
<p><em>italic</em></p>\
<p><em>italic</em></p>
<em>italic</em>\
<em>italic</em>\
<em>italic</em>
"""
)
}

/// 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),
"""
<p><strong>bold</strong></p>\
<p><strong>bold</strong></p>
<strong>bold</strong>\
<strong>bold</strong>\
<strong>bold</strong>
"""
)
}

/// 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),
"""
<p><em><strong>bold and italic</strong></em></p>\
<p><em><strong>bold and italic</strong></em></p>
<em><strong>bold and italic</strong></em>\
<em><strong>bold and italic</strong></em>
"""
)
}

/// 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),
"""
<p><code>code</code></p>
<code>code</code>\
<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),
"""
<p><del>strikethrough</del></p>\
<p><del>strikethrough</del></p>
<del>strikethrough</del>\
<del>strikethrough</del>\
<del>strikethrough</del>
"""
)
}

/// 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: "[email protected]")")
}

XCTAssertEqual(try renderer.render(view: view),
"""
<p><a href="https://www.vapor.codes" target="_blank">Link</a></p>
<a href="https://www.vapor.codes" target="_blank">Link</a>\
<a href="https://www.vapor.codes" target="_blank">https://www.vapor.codes</a>\
<a href="mailto:[email protected]" target="_blank">[email protected]</a>
"""
)
}

/// Tests the Markdown rendering of a paragraph with multiple emphasis elements
func testRenderingMarkdownParagraph() throws {

let view = TestView {
Expand All @@ -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),
"""
<p><strong>This text is <em>extremely</em> important.</strong></p>
<strong>This text is <em>extremely</em> important.</strong>
"""
)
}
Expand Down
Loading