diff --git a/.codecov.yml b/.codecov.yml index f9f4b3c..fea7da7 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -2,3 +2,4 @@ coverage: range: "0...100" ignore: - "Tests/" + - ".build/" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4eaaf58..86bcb16 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,17 +1,20 @@ name: CI on: -- push + push: + branches: + - master + pull_request: jobs: xenial: container: - image: vapor/swift:5.1-xenial + image: vapor/swift:5.2-xenial runs-on: ubuntu-latest steps: - uses: actions/checkout@master - run: swift test --enable-test-discovery --enable-code-coverage bionic: container: - image: vapor/swift:5.1-bionic + image: vapor/swift:5.2-bionic runs-on: ubuntu-latest steps: - uses: actions/checkout@master @@ -20,7 +23,7 @@ jobs: - name: Setup container for codecov upload run: apt-get update && apt-get install curl - name: Process coverage file - run: llvm-cov show .build/x86_64-unknown-linux/debug/LeafMarkdownPackageTests.xctest -instr-profile=.build/x86_64-unknown-linux/debug/codecov/default.profdata > coverage.txt + run: llvm-cov show .build/x86_64-unknown-linux-gnu/debug/LeafMarkdownPackageTests.xctest -instr-profile=.build/debug/codecov/default.profdata > coverage.txt - name: Upload code coverage uses: codecov/codecov-action@v1 with: diff --git a/Package.swift b/Package.swift index 3ad6fb5..05a9734 100644 --- a/Package.swift +++ b/Package.swift @@ -1,19 +1,27 @@ -// swift-tools-version:5.1 +// swift-tools-version:5.2 import PackageDescription let package = Package( name: "LeafMarkdown", + platforms: [ + .macOS(.v10_15) + ], products: [ .library(name: "LeafMarkdown", targets: ["LeafMarkdown"]), ], dependencies: [ - .package(url: "https://github.com/vapor/template-kit.git", from: "1.4.0"), - .package(url: "https://github.com/vapor-community/markdown.git", from: "0.5.0"), - .package(url: "https://github.com/vapor/leaf.git", from: "3.0.0"), + .package(name: "SwiftMarkdown", url: "https://github.com/vapor-community/markdown.git", from: "0.5.0"), + .package(url: "https://github.com/vapor/leaf-kit.git", from: "1.0.0-rc.1"), ], targets: [ - .target(name: "LeafMarkdown", dependencies: ["TemplateKit", "SwiftMarkdown"]), - .testTarget(name: "LeafMarkdownTests", dependencies: ["LeafMarkdown", "Leaf"]), + .target(name: "LeafMarkdown", dependencies: [ + .product(name: "LeafKit", package: "leaf-kit"), + .product(name: "SwiftMarkdown", package: "SwiftMarkdown"), + ]), + .testTarget(name: "LeafMarkdownTests", dependencies: [ + .target(name: "LeafMarkdown"), + .product(name: "LeafKit", package: "leaf-kit"), + ]), ] ) diff --git a/Package@swift-4.swift b/Package@swift-4.swift deleted file mode 100644 index 0553068..0000000 --- a/Package@swift-4.swift +++ /dev/null @@ -1,19 +0,0 @@ -// swift-tools-version:4.0 - -import PackageDescription - -let package = Package( - name: "LeafMarkdown", - products: [ - .library(name: "LeafMarkdown", targets: ["LeafMarkdown"]), - ], - dependencies: [ - .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"), - .package(url: "https://github.com/vapor/leaf.git", from: "3.0.0"), - .package(url: "https://github.com/vapor-community/markdown.git", .upToNextMajor(from: "0.4.0")), - ], - targets: [ - .target(name: "LeafMarkdown", dependencies: ["Vapor", "Leaf", "SwiftMarkdown"]), - .testTarget(name: "LeafMarkdownTests", dependencies: ["LeafMarkdown"]), - ] -) diff --git a/Sources/LeafMarkdown/Tag.swift b/Sources/LeafMarkdown/Tag.swift index 6c4b736..593ae78 100644 --- a/Sources/LeafMarkdown/Tag.swift +++ b/Sources/LeafMarkdown/Tag.swift @@ -1,42 +1,34 @@ -import TemplateKit +import LeafKit import SwiftMarkdown -public final class Markdown: TagRenderer { - +public struct Markdown: LeafTag { public enum Error: Swift.Error { - case invalidArgument(TemplateData?) + case invalidArgument(LeafData?) } - - public let name = "markdown" - + private let options: MarkdownOptions? - + public init(options: MarkdownOptions? = nil) { self.options = options } - - public func render(tag: TagContext) throws -> Future { - + + public func render(_ ctx: LeafContext) throws -> LeafData { var markdown = "" - - if let markdownArgument = tag.parameters.first, !markdownArgument.isNull { + + if let markdownArgument = ctx.parameters.first, !markdownArgument.isNull { guard let markdownArgumentValue = markdownArgument.string else { - throw Error.invalidArgument(tag.parameters.first) + throw Error.invalidArgument(ctx.parameters.first) } markdown = markdownArgumentValue } - let markdownHTML: String = try { - if let options = options { - return try markdownToHTML(markdown, options: options) - } else { - return try markdownToHTML(markdown) - } - }() - - return Future.map(on: tag) { - .string(markdownHTML) + let markdownHTML: String + if let options = options { + markdownHTML = try markdownToHTML(markdown, options: options) + } else { + markdownHTML = try markdownToHTML(markdown) } - } + return .string(markdownHTML) + } } diff --git a/Tests/LeafMarkdownTests/LeafTests.swift b/Tests/LeafMarkdownTests/LeafTests.swift index 73c3592..ed7719b 100644 --- a/Tests/LeafMarkdownTests/LeafTests.swift +++ b/Tests/LeafMarkdownTests/LeafTests.swift @@ -1,73 +1,89 @@ import XCTest -@testable import Leaf +@testable import LeafKit import LeafMarkdown -class LeafTests: XCTestCase { - +class MarkdownTests: XCTestCase { // MARK: - Properties var renderer: LeafRenderer! - let template = "#markdown(data)" + var template: ResolvedDocument! // MARK: - Overrides override func setUp() { - let queue = EmbeddedEventLoop() - let container = BasicContainer(config: .init(), environment: .testing, services: .init(), on: queue) - let tag = Markdown() - var leafTagConfig = LeafTagConfig.default() - leafTagConfig.use(tag, as: tag.name) - self.renderer = LeafRenderer(config: LeafConfig(tags: leafTagConfig, viewsDir: "", shouldCache: false), using: container) + let loop = EmbeddedEventLoop() + let config = LeafConfiguration(rootDirectory: Process().currentDirectoryPath) + var tags = defaultTags + tags["markdown"] = Markdown() + self.renderer = LeafRenderer( + configuration: config, + tags: tags, + files: NIOLeafFiles(fileio: .init(threadPool: .init(numberOfThreads: 1))), + eventLoop: loop + ) + + do { + var lexer = LeafLexer(name: "markdowntest", template: "#markdown(data)") + let tokens = try lexer.lex() + var parser = LeafParser(name: "markdowntest", tokens: tokens) + let syntax = try parser.parse() + let unresolved = UnresolvedDocument(name: "markdowntest", raw: syntax) + let resolver = ExtendResolver(document: unresolved, dependencies: []) + template = try resolver.resolve(rootDirectory: config.rootDirectory) + } catch { + XCTFail() + } } // MARK: - Tests func testRunTag() throws { let inputMarkdown = "# This is a test\n\nWe have some text in a tag" - let data = TemplateData.dictionary(["data": .string(inputMarkdown)]) let expectedHtml = "

This is a test

\n

We have some text in a tag

\n" - let result = try renderer.render(template: template.data(using: .utf8)!, data).wait() - let resultString = String(data: result.data, encoding: .utf8)! + let result = try renderer.render(template, context: ["data": .string(inputMarkdown)]) + let resultString = result.getString(at: 0, length: result.readableBytes) XCTAssertEqual(resultString, expectedHtml) } func testNilParameterDoesNotCrashLeaf() throws { - let data = TemplateData.dictionary(["data": .null]) let expectedHtml = "" - - let result = try renderer.render(template: template.data(using: .utf8)!, data).wait() - let resultString = String(data: result.data, encoding: .utf8)! + let result = try renderer.render(template, context: ["data": .null]) + let resultString = result.getString(at: 0, length: result.readableBytes) XCTAssertEqual(resultString, expectedHtml) } func testStripHtml() throws { let inputMarkdown = "
" - let data = TemplateData.dictionary(["data": .string(inputMarkdown)]) let expectedHtml = "\n" - let result = try renderer.render(template: template.data(using: .utf8)!, data).wait() - let resultString = String(data: result.data, encoding: .utf8)! + let result = try renderer.render(template, context: ["data": .string(inputMarkdown)]) + let resultString = result.getString(at: 0, length: result.readableBytes) XCTAssertEqual(resultString, expectedHtml) + } + func testRejectBadData() throws { + let data = LeafData.lazy { .null } + XCTAssertThrowsError(try renderer.render(template, context: ["data": data])) } func testDoNotStripHtml() throws { - - let queue = EmbeddedEventLoop() - let container = BasicContainer(config: .init(), environment: .testing, services: .init(), on: queue) - let tag = Markdown(options: []) - var leafTagConfig = LeafTagConfig.default() - leafTagConfig.use(tag, as: tag.name) - let renderer = LeafRenderer(config: LeafConfig(tags: leafTagConfig, viewsDir: "", shouldCache: false), - using: container) + let loop = EmbeddedEventLoop() + let config = LeafConfiguration(rootDirectory: Process().currentDirectoryPath) + var tags = defaultTags + tags["markdown"] = Markdown(options: [.unsafe]) + let renderer = LeafRenderer( + configuration: config, + tags: tags, + files: NIOLeafFiles(fileio: .init(threadPool: .init(numberOfThreads: 1))), + eventLoop: loop + ) let inputMarkdown = "
" - let data = TemplateData.dictionary(["data": .string(inputMarkdown)]) let expectedHtml = "
\n" - let result = try renderer.render(template: template.data(using: .utf8)!, data).wait() - let resultString = String(data: result.data, encoding: .utf8)! + let result = try renderer.render(template, context: ["data": .string(inputMarkdown)]) + let resultString = result.getString(at: 0, length: result.readableBytes) XCTAssertEqual(resultString, expectedHtml) } }