Skip to content
This repository has been archived by the owner on Oct 17, 2021. It is now read-only.

Move render method from Document to Node #18

Merged
merged 3 commits into from
May 1, 2020
Merged
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
7 changes: 7 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added a changelog.
#17 by @mattt.

### Changed

- Changed `render` method,
as well as nested `RenderingFormat` and `RenderingOptions` types,
from `Document` to `Node`.
#18 by @mattt.

### Fixed

- Fixed abbreviation for "Universal Declaration of Human Rights" (UDHR)
Expand Down
101 changes: 0 additions & 101 deletions Sources/CommonMark/Nodes/Document.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,107 +71,6 @@ public final class Document: Node {
append(child: child)
}
}

// MARK: - Rendering

/// Formats for rendering a document.
public enum RenderingFormat {
/// CommonMark
case commonmark

/// HTML
case html

/// XML
case xml

/// LaTeX
case latex

/// Manpage
case manpage
}

/// Options for rendering a CommonMark document.
public struct RenderingOptions: OptionSet {
public var rawValue: Int32

public init(rawValue: Int32 = CMARK_OPT_DEFAULT) {
self.rawValue = rawValue
}

/**
Render raw HTML and "unsafe" links.

A link is considered to be "unsafe"
if its scheme is `javascript:`, `vbscript:`, or `file:`,
or if its scheme is `data:`
and the MIME type of the encoded data isn't one of the following:

- `image/png`
- `image/gif`
- `image/jpeg`
- `image/webp`

By default,
raw HTML is replaced by a placeholder HTML comment.
Unsafe links are replaced by empty strings.

- Important: This option has an effect only when rendering HTML.
*/
public static let unsafe = RenderingOptions(rawValue: CMARK_OPT_UNSAFE)

/**
Render softbreak elements as spaces.

- Important: This option has no effect when rendering XML.
*/
public static let noBreaks = RenderingOptions(rawValue: CMARK_OPT_NOBREAKS)

/**
Render softbreak elements as hard line breaks.

- Important: This option has no effect when rendering XML.
*/
public static let hardBreaks = RenderingOptions(rawValue: CMARK_OPT_HARDBREAKS)

/**
Include a `data-sourcepos` attribute on all block elements
to map the rendered output to the source input.

- Important: This option has an effect only when rendering HTML or XML.
*/
public static let includeSourcePosition = RenderingOptions(rawValue: CMARK_OPT_SOURCEPOS)
}

/**
Render a document into a given format with the specified options.

- Parameters:
- format: The rendering format
- options: The rendering options
- width: The column width used to wrap lines for rendered output
(`.commonmark`, `.man`, and `.latex` formats only).
Must be a positive number.
Pass `0` to prevent line wrapping.
- Returns: The rendered text.
*/
public func render(format: RenderingFormat, options: RenderingOptions = [], width: Int = 0) -> String {
precondition(width >= 0)

switch format {
case .commonmark:
return String(cString: cmark_render_commonmark(cmark_node, options.rawValue, Int32(clamping: width)))
case .html:
return String(cString: cmark_render_html(cmark_node, options.rawValue))
case .xml:
return String(cString: cmark_render_xml(cmark_node, options.rawValue))
case .latex:
return String(cString: cmark_render_latex(cmark_node, options.rawValue, Int32(clamping: width)))
case .manpage:
return String(cString: cmark_render_man(cmark_node, options.rawValue, Int32(clamping: width)))
}
}
}

// MARK: - Comparable
Expand Down
101 changes: 101 additions & 0 deletions Sources/CommonMark/Nodes/Node.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,107 @@ public class Node: Codable {
return Node.create(for: cmark_node_parent(cmark_node))
}

// MARK: - Rendering

/// Formats for rendering a document.
public enum RenderingFormat {
/// CommonMark
case commonmark

/// HTML
case html

/// XML
case xml

/// LaTeX
case latex

/// Manpage
case manpage
}

/// Options for rendering a CommonMark document.
public struct RenderingOptions: OptionSet {
public var rawValue: Int32

public init(rawValue: Int32 = CMARK_OPT_DEFAULT) {
self.rawValue = rawValue
}

/**
Render raw HTML and "unsafe" links.

A link is considered to be "unsafe"
if its scheme is `javascript:`, `vbscript:`, or `file:`,
or if its scheme is `data:`
and the MIME type of the encoded data isn't one of the following:

- `image/png`
- `image/gif`
- `image/jpeg`
- `image/webp`

By default,
raw HTML is replaced by a placeholder HTML comment.
Unsafe links are replaced by empty strings.

- Important: This option has an effect only when rendering HTML.
*/
public static let unsafe = RenderingOptions(rawValue: CMARK_OPT_UNSAFE)

/**
Render softbreak elements as spaces.

- Important: This option has no effect when rendering XML.
*/
public static let noBreaks = RenderingOptions(rawValue: CMARK_OPT_NOBREAKS)

/**
Render softbreak elements as hard line breaks.

- Important: This option has no effect when rendering XML.
*/
public static let hardBreaks = RenderingOptions(rawValue: CMARK_OPT_HARDBREAKS)

/**
Include a `data-sourcepos` attribute on all block elements
to map the rendered output to the source input.

- Important: This option has an effect only when rendering HTML or XML.
*/
public static let includeSourcePosition = RenderingOptions(rawValue: CMARK_OPT_SOURCEPOS)
}

/**
Render a document into a given format with the specified options.

- Parameters:
- format: The rendering format
- options: The rendering options
- width: The column width used to wrap lines for rendered output
(`.commonmark`, `.man`, and `.latex` formats only).
Must be a positive number.
Pass `0` to prevent line wrapping.
- Returns: The rendered text.
*/
public func render(format: RenderingFormat, options: RenderingOptions = [], width: Int = 0) -> String {
precondition(width >= 0)

switch format {
case .commonmark:
return String(cString: cmark_render_commonmark(cmark_node, options.rawValue, Int32(clamping: width)))
case .html:
return String(cString: cmark_render_html(cmark_node, options.rawValue))
case .xml:
return String(cString: cmark_render_xml(cmark_node, options.rawValue))
case .latex:
return String(cString: cmark_render_latex(cmark_node, options.rawValue, Int32(clamping: width)))
case .manpage:
return String(cString: cmark_render_man(cmark_node, options.rawValue, Int32(clamping: width)))
}
}

// MARK: - Codable

public required convenience init(from decoder: Decoder) throws {
Expand Down
17 changes: 17 additions & 0 deletions Tests/CommonMarkTests/DocumentRenderingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ final class DocumentRenderingTests: XCTestCase {
XCTAssertEqual(document.render(format: .commonmark, width: 60), expected)
}

func testNodeCommonMarkRendering() throws {
let document = try Document(Fixtures.udhr)

for child in document.children {
XCTAssertEqual(child.render(format: .commonmark), child.description)
}
}

func testDocumentHTMLRendering() throws {
let document = try Document(Fixtures.udhr)

Expand All @@ -34,6 +42,15 @@ final class DocumentRenderingTests: XCTestCase {
XCTAssertEqual(document.render(format: .html), expected)
}

func testNodeHTMLRendering() throws {
let document = try Document(Fixtures.udhr)

let expected = document.children.map { $0.render(format: .html) }.joined()
let actual = document.render(format: .html)

XCTAssertEqual(expected, actual)
}

func testDocumentXMLRendering() throws {
let document = try Document(Fixtures.udhr)

Expand Down