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

Create custom sequence to access child nodes #228

Merged
merged 7 commits into from
Oct 9, 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
4 changes: 4 additions & 0 deletions Down.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

/* Begin PBXBuildFile section */
14C5E33521877CE900D5380C /* DownView.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D41689B51CFFE6BB00E5802B /* DownView.bundle */; };
26CABB93252B4D490032183C /* ChildSequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26CABB92252B4D490032183C /* ChildSequence.swift */; };
8A569F481E6B3ED2008BE2AC /* DownView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D43AE5D91CFFD0D0006E1522 /* DownView.swift */; };
8A569F491E6B3ED9008BE2AC /* blocks.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201EF71CFA5D63008EEC6E /* blocks.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
8A569F4A1E6B3ED9008BE2AC /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = D4201EF81CFA5D63008EEC6E /* buffer.c */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
Expand Down Expand Up @@ -211,6 +212,7 @@

/* Begin PBXFileReference section */
14C5E33621877FCD00D5380C /* DownView (macOS).bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = "DownView (macOS).bundle"; sourceTree = "<group>"; };
26CABB92252B4D490032183C /* ChildSequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChildSequence.swift; sourceTree = "<group>"; };
8A569F401E6B3E50008BE2AC /* Down.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Down.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8AFAEAFB1E6E32E900E09B68 /* DownTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DownTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8C73B9B522A687C400C8E60F /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
Expand Down Expand Up @@ -708,6 +710,7 @@
EEEBEE68225D2B1200AE438D /* Strong.swift */,
EEEBEE5A225D2A7E00AE438D /* Text.swift */,
EEEBEE58225D2A7000AE438D /* ThematicBreak.swift */,
26CABB92252B4D490032183C /* ChildSequence.swift */,
);
path = Nodes;
sourceTree = "<group>";
Expand Down Expand Up @@ -942,6 +945,7 @@
EEEBEE63225D2AD400AE438D /* HtmlInline.swift in Sources */,
8A569F621E6B3ED9008BE2AC /* node.c in Sources */,
EE4484932301F2DB0065C836 /* CGRect+Helpers.swift in Sources */,
26CABB93252B4D490032183C /* ChildSequence.swift in Sources */,
EEEBEE6D225D2B3200AE438D /* Image.swift in Sources */,
EED8DA9722BECD7500E54492 /* FontCollection.swift in Sources */,
EEEBEE4D225D2A0200AE438D /* Item.swift in Sources */,
Expand Down
20 changes: 2 additions & 18 deletions Source/AST/Nodes/BaseNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,8 @@ import libcmark
public class BaseNode: Node {

public let cmarkNode: CMarkNode

public private(set) lazy var children: [Node] = {
var result: [Node] = []
var child = cmark_node_first_child(cmarkNode)

while let raw = child {

guard let node = raw.wrap() else {
assertionFailure("Couldn't wrap node of type: \(raw.type)")
continue
}

result.append(node)
child = cmark_node_next(child)
}

return result
}()

public private(set) lazy var children: [Node] = Array(childSequence)

public private(set) lazy var nestDepth: Int = {
var depth = 0
Expand Down
34 changes: 34 additions & 0 deletions Source/AST/Nodes/ChildSequence.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// ChildSequence.swift
// Down
//
// Created by Sven Weidauer on 05.10.2020
//

import libcmark

/// Sequence of child nodes
public struct ChildSequence: Sequence {
let node: CMarkNode

public struct Iterator: IteratorProtocol {
var node: CMarkNode?

public mutating func next() -> Node? {
guard let node = node else { return nil }
defer { self.node = cmark_node_next(node) }

guard let result = node.wrap() else {
assertionFailure("Couldn't wrap node of type: \(node.type)")
return nil
}

return result
}
}

public func makeIterator() -> Iterator {
return Iterator(node: cmark_node_first_child(node))
}
}

5 changes: 5 additions & 0 deletions Source/AST/Nodes/Node.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public extension Node {
var hasSuccessor: Bool {
return cmark_node_next(cmarkNode) != nil
}

/// Sequence of wrapped child nodes.
var childSequence: ChildSequence {
return ChildSequence(node: cmarkNode)
}
}

// MARK: - Helper extensions
Expand Down
2 changes: 1 addition & 1 deletion Source/AST/Visitors/Visitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public protocol Visitor {

extension Visitor {
public func visitChildren(of node: Node) -> [Result] {
return node.children.compactMap { child in
return node.childSequence.compactMap { child in
switch child {
case let child as Document: return visit(document: child)
case let child as BlockQuote: return visit(blockQuote: child)
Expand Down
15 changes: 15 additions & 0 deletions Source/Renderers/DownASTRenderable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ extension DownASTRenderable {
public func toAST(_ options: DownOptions = .default) throws -> UnsafeMutablePointer<cmark_node> {
return try DownASTRenderer.stringToAST(markdownString, options: options)
}

/// Parses the `markdownString` property into an abstract syntax tree and returns the root `Document` node.
///
/// - Parameter options: `DownOptions` to modify parsing or rendering, defaulting to `.default`
/// - Returns: The root Document node for the abstract syntax tree representation of the Markdown input
/// - Throws: `MarkdownToASTError` if conversion fails
public func toDocument(_ options: DownOptions = .default) throws -> Document {
let tree = try toAST(options)

guard tree.type == CMARK_NODE_DOCUMENT else {
throw DownErrors.astRenderingError
}

return Document(cmarkNode: tree)
}
}

public struct DownASTRenderer {
Expand Down
8 changes: 1 addition & 7 deletions Source/Renderers/DownAttributedStringRenderable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,7 @@ extension DownAttributedStringRenderable {
/// - Returns: An `NSAttributedString`
/// - Throws: `DownErrors` depending on the scenario
public func toAttributedString(_ options: DownOptions = .default, styler: Styler) throws -> NSAttributedString {
let tree = try self.toAST(options)

guard tree.type == CMARK_NODE_DOCUMENT else {
throw DownErrors.astRenderingError
}

let document = Document(cmarkNode: tree)
let document = try self.toDocument(options)
let visitor = AttributedStringVisitor(styler: styler, options: options)
return document.accept(visitor)
}
Expand Down
3 changes: 1 addition & 2 deletions Tests/AST/NodeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ extension NodeTests {

private func parse(_ markdown: String, andVisitWith visitor: NodeVisitor) {
do {
let ast = try Down(markdownString: markdown).toAST()
let document = Document(cmarkNode: ast)
let document = try Down(markdownString: markdown).toDocument()
document.accept(visitor)
} catch {
XCTFail()
Expand Down
3 changes: 1 addition & 2 deletions Tests/AST/VisitorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ class VisitorTests: XCTestCase {

func debugResult(for markdown: String) -> String {
let down = Down(markdownString: markdown)
let ast = try! down.toAST()
let document = Document(cmarkNode: ast)
let document = try! down.toDocument()
return document.accept(DebugVisitor())
}

Expand Down